【51CTO.com快译】本文将介绍一些微服务的优秀实践,并提出帮助开发人员设计、编排和保护微服务架构的一些方法。通过了解这些实践,将为开发人员成功开发项目提供帮助。

微服务的好处和挑战

在深入研究微服务优秀实践之前,应该首先了解微服务的好处和挑战,以及为什么要使用它们的原因。

简而言之,微服务是一种改进的软件架构,可以让开发人员:

  • 更快地部署和扩展。更小的应用程序域允许自动化,从而实现更快的部署和更快的扩展。

  • 减少停机时间。限制不可用服务对主要业务功能的影响,从而提高其整体业务的正常运行时间。

  • 确保可用性。使微服务之间的功能保持离散,从而限制实例宕机时的影响。

当然采用微服务拥有这些好处,也会面临着一系列新的挑战,其中包括服务间通信、安全性和可扩展性。

  • 服务间通信。对于单体应用来说,所有模块都可以固有地相互通信。因此需要管理一个证书,一旦请求经过身份验证和授权,就可以毫无问题地遍历代码路径。当开发人员从单体架构中提取一个功能到微服务应用程序时,曾经的内部函数调用变成了需要对这个外部微服务进行身份验证和授权的外部API调用。

  • 安全层。认证和授权在单体应用中,可以在入口处一次性处理。随着向微服务的过渡,每个微服务都需要执行一些身份验证和授权以强制执行访问控制。但是要求用户每次使用不同的微服务都要进行登录是不现实的,因此需要建立一个全面的认证策略。

  • 可扩展性。尽管微服务允许开发人员快速扩展独立功能,但要有效地做到这一点,需要良好的应用程序管理甚至更好的工具。可扩展性的有效性取决于开发人员的微服务编排平台,以下将更详细地进行讨论。

微服务的优秀实践

在对微服务的好处和挑战的快速概述之后,以下深入研究微服务的一些优秀实践。这些优秀实践将帮助开发人员创建一个强大、易于管理、可扩展且安全的互通微服务系统。

1.较小的应用程序域

采用微服务策略需要遵循单一职责原则。通过限制单一服务的责任范围,可以降低该服务失败的负面影响。如果单个微服务的责任太多,发生故障或不可用将对系统的其余部分产生多米诺骨牌效应。

顾名思义,微服务是微小的服务,而保持微服务的应用程序域很小,可以专用于一项逻辑功能。如果出现任何问题,这将减少特定的微服务的影响。此外,较小的服务更易于维护,其结果是更容易更新和更快的开发。

那么这在实践中是什么样子的?例如,假设微服务是一个API服务器,它接受获取数据的请求,并且这些请求必须附带一个授权令牌。在刚开始时,这是唯一需要授权令牌的微服务。为什么不将身份验证和令牌生成作为微服务的一部分?乍一看,其优点是活动部件少,管理工作少。

当然,开发人员如果拥有需要授权令牌的其他服务,则很快就会发现原来的微服务将充当API服务器和身份验证服务器。如果API服务器宕机,那么其身份验证服务器也会随之宕机。这样,所有其他需要授权令牌的服务也是如此。

因此考虑未来的发展,开发人员需要保持微服务的微小化。

2.数据存储分离

连接到同一个数据库的多个微服务本质上仍然是一个单体架构。单体应用只是运行在数据库层而不是应用层,这使得它同样脆弱。每个微服务都应该尽可能地拥有自己的数据持久层。这不仅确保了与其他微服务的隔离,而且如果特定数据集变得不可用,还可以最大限度地减少影响范围。

有时,不同的微服务访问同一数据库中的数据似乎是有意义的。然而,更深入的研究可能会发现,一个微服务仅适用于数据库表的子集,而另一个微服务仅适用于完全不同的数据库表子集。如果这两个数据子集是完全正交的,那么这将是将数据库分离为单独服务的一个很好的例子。这样,一个服务依赖于其专用数据存储,并且该数据存储的故障不会影响除该服务之外的任何服务。

以文件存储为例。在采用微服务架构时,不需要单独的微服务使用相同的文件存储服务。除非有实际的文件重叠,否则单独的微服务应该有单独的文件存储。

这种数据分离提高了灵活性。例如,假设有两个微服务都与云计算提供商共享相同的文件存储服务。其中一个微服务经常接触大量文件,但这些文件很小,而另一个微服务只有几个定期访问的文件,但这些文件的大小很大,达到数百GB。

对这两个微服务使用通用的文件存储服务将会降低优化成本的灵活性,这是因为同时拥有大文件和小文件以及定期访问的混合。如果每个微服务都有自己的数据持久层(当然可以是一个单独的微服务),那么就可以更灵活地找到更适合该单个微服务需求的提供者或服务。

成本优化、选项的灵活性以及对可能失败的单一解决方案的更少依赖,这些都是分离不同微服务数据的原因。

3.沟通渠道

微服务之间如何沟通需要深思熟虑,特别是在关注的事件方面。否则,单个不可用的服务可能导致通信中断,并可能导致整个应用程序崩溃。

例如在一个在线商店的微服务系统中,一个微服务接受在网站下的订单;另一个微服务向客户发送一条文本通知,告知收到了他们的订单;第三个微服务通知仓库发出产品。最后,第四个微服务更新库存计数。

微服务之间有两种通信方式:同步和异步。如果使用同步通信来处理上述示例,Web服务器可能会通过首先向客户通知服务发送请求来处理新订单。客户通知服务在得到响应之后,Web服务器向仓库通知服务发送请求,然后再次等待响应。最后,Web服务器向库存更新程序发送请求。这个同步方法如图1所示:

图1 微服务之间的同步通信

当然,在客户通知服务发生故障情况下,通知客户的请求可能会超时或返回错误,或者可能让Web服务器无限期地等待响应。那么仓库通知服务可能永远不会收到发送请求。而微服务之间的同步通信可以创建一个依赖链,如果链中的任何连接中断,该链就会中断。

在异步通信中,服务发送请求并在不等待响应的情况下继续发送。在一种可能的异步方法中,Web服务器可能会发送“通知客户”请求,然后完成其任务。客户通知服务负责通知客户并向仓库通知服务发送异步请求,仓库通知服务负责向库存更新服务发送请求。这个示例如图2所示:

图2 微服务之间的链式异步通信

当然在这个模型中,看到异步通信仍然会产生依赖链,单个服务的故障仍然会中断应用程序。

异步通信的一种简单但有效的方法是采用发布/订阅模式。当感兴趣的事件发生时,生产者(在本例中为微服务)将该事件的记录发布到消息队列服务。对此类事件感兴趣的任何其他微服务作为该事件的消费者订阅消息队列服务。微服务只与消息队列服务交谈和监听,而不是彼此通信。

这个示例如图3所示:

图3 消息队列服务促进异步通信

消息队列是一个独立的服务,与所有微服务分离。它负责接收已发布的事件并通知订阅者发生的这些事件。这确保了一个微服务的故障(可能意味着消息延迟传递),但对其他相关但不关心的服务的影响最小。

有很多工具可以完成这种异步通信(例如Kafka或RabbitMQ)。因此需要寻找将这些工具集成为微服务异步通信主干的方法。

在有些情况下,微服务之间需要同步通信。大多数请求-响应交互出于必要是同步的。例如,查询数据库的API服务器必须等待查询响应;获取缓存数据的Web服务器必须等待键值存储响应。

当需要同步通信时,开发人员需要使用开源Kong Gateway来确保其通信快速可靠地路由到正确的微服务。

4.兼容性

尽可能保持向后兼容性,这样消费者就不会遇到损坏的API。实现这一点的常用方法是遵循路径级兼容性保证,如/api/v1或/api/v2。任何向后不兼容的更改都会转到新路径,如/api/v3。

然而,尽管开发人员作为软件工程师尽了最大的努力,但有时还是需要弃用API,所以不会一直运行它们。使用API网关请求转换插件,其微服务可以通过在原始API响应旁边轻松注入弃用通知或附加类似于Kubernetes的“弃用标头”来提醒API使用者。

5.编排微服务

微服务的编排是流程和工具成功的关键因素。从技术上讲,开发人员可以使用systemd和Docker或podman之类的东西在虚拟机上运行容器,但这无法提供与容器编排平台相同级别的弹性。这会对采用微服务架构带来的正常运行时间和可用性优势产生负面影响。对于有效的微服务编排,开发人员需要依赖经过实战考验的容器编排平台;该领域的领导者显然是Kubernetes。

Kubernetes管理所有容器的配置和部署,同时处理负载平衡、扩展、高可用性副本集和网络通信问题。

开发人员可以在本地部署Kubernetes,也可以在Azure Kubernetes Service、Red Hat OpenShift或Amazon Elastic Kubernetes Service中使用。Kubernetes内置的调度、复制和网络功能使微服务编排比在传统操作系统上容易得多。

将Kubernetes与Kuma服务网格和Kong Ingress Controller结合使用,就创建了可发现、受监控且具有弹性的微服务。

6.微服务安全

随着应用程序包含越来越多的微服务,确保适当的安全性可能会变得复杂。用于执行安全策略的集中式系统对于保护应用程序免受恶意用户、黑客和错误代码的侵害至关重要。无论是在虚拟机上还是在Kubernetes上运行,Kong都应该是开发人员使用微服务的安全故事的开始。Kong维护的大量安全插件可以轻松满足微服务的一些最常见的需求,其中包括身份验证、授权、流量控制和速率限制。

示例:使用Kong Ingress Controller进行速率限制

为了演示工作中的安全插件示例,将部署Kong的速率限制(Rate Limiting)插件,以展示Kong如何防止对应用程序的过多入站请求。将使用kind创建一个本地Kubernetes集群,然后按照以下说明部署Kong Ingress控制器。

在创建集群并部署Kong Ingress Controller之后,第一步是设置速率限制插件。可以为不同的范围设置插件。将使用Kubernetes集群上的默认项目作为用例,并将插件范围限定为默认命名空间。

然后为该服务创建一个“echo服务”和一个入口。在本例中,采用了Kong的Kubernetes Ingress控制器入门文档中的示例:

需要做的最后一件事就是测试,将从Kubernetes文档中借用shell-demo进行集群内测试:

在进入shellpod之前,需要kong-proxy的集群IP:

现在,可以通过shell访问的pod并测试速率限制:

大多数云计算提供商不需要使用中间pod来测试速率限制的额外步骤,这为开发人员提供了开箱即用的负载均衡器。在这种情况下,由于使用的是kind,因此没有配置负载均衡器,而这个测试来自集群内部。如果有可用的负载平衡器,同样的测试也可以在外部进行。

速率限制只是一个例子,说明Kong能够满足整体微服务战略和优秀实践的安全考虑,并且可以轻松提供全面的解决方案。Kong维护多个插件和产品,以使通信渠道万无一失、API更改影响最小化,并使应用程序域易于管理。另外,它与大多数编程语言和供应商选项兼容。

7.指标和监控

基于微服务的架构可能导致数百或数千个小型模块化服务的大规模扩展。尽管这为提高速度、可用性和覆盖范围带来了巨大潜力,但一个庞大的微服务系统需要一种战略性和系统性的监控方法。通过密切关注所有的微服务,将确保它们能够正常运行,对用户可用,并正确使用资源。当这些期望中的任何一个没有得到满足时,可以采取适当的行动来应对。

如今有多种广泛采用的监控解决方案可以无缝集成到基础设施中。一些解决方案使用指标导出器SDK,可以通过在微服务中添加一两行代码来集成。其他的可以作为插件与API网关或服务网格集成,用于监控网络问题和资源使用情况。

通过监控微服务并清楚地显示数字,可以就如何保持微服务的健康运行和可用性做出明智的决策。在这样做时,将会让用户感到满意。

采用监控工具收集指标时,可视化工具和仪表盘可以使用这些指标,帮助查看微服务背后的数字。例如,上周三晚上8点有多少用户在线?自从发布这个新特性以来,CPU负载增加了多少?产品发货API和发票API之间的延迟是多少?

结语

微服务是一个令人兴奋的旅程。企业在开始时从更快的部署和可扩展性、减少停机时间以及全面提高业务可用性获得令人难以置信的好处。然后再加入编排平台,以及一些由Kong及其插件支持的优秀实践,以上只介绍了Kong所能做的一小部分,因此强烈建议查看Kong Hub所有可用的功能,以简化微服务之旅。

原文标题:7 Microservices Best Practices for Developers,作者:Michael Bogan