10个微服务设计模式以实现更好的架构


历史上,单体架构被开发人员使用了很长一段时间,并且在很长一段时间内它都有效。不幸的是,这些架构使用的部件较少但较大,因此这意味着如果单个部件发生故障,它们更有可能整体发生故障。通常,这些应用程序作为单个进程运行,这只会加剧问题。

微服务通过让每个微服务作为单独的进程运行来解决这些特定问题。如果一个齿轮发生故障,并不一定意味着整台机器停止运行。此外,诊断和修复较小的、高度内聚的服务中的缺陷通常比较大的整体服务更容易。

微服务设计模式提供了经过验证的基本构建块,可以帮助编写微服务代码。通过在开发过程中利用模式,与从头开始为微服务应用程序编写代码相比,您可以节省时间并确保更高的准确性。在本文中,我们全面概述了您需要了解的 10 种微服务设计模式,以及何时应用它们。

使用微服务设计模式的主要好处
了解微服务的主要优点将帮助您理解设计模式。确切的好处可能会根据所使用的微服务及其所使用的应用程序而有所不同。然而,开发人员和软件工程师在使用微服务设计模式时通常可以期待以下优势:

  • 创建可独立部署且去中心化的应用程序架构
  • 在需要时实现大规模可扩展性
  • 可以增量推出的新版本微服务,从而减少停机时间
  • 在旧应用程序版本被完全替换之前检测不需要的行为
  • 使用多种编码语言
  • 预防因孤立组件的根本原因而导致的系统故障
  • 实时负载均衡

在 Capital One,我们应用微服务架构来帮助提高交付速度而不影响质量,因此我们拥有使用此类设计模式的第一手经验。当然,了解微服务最佳实践将帮助您获得最大收益。在采用任何最佳实践之前,第一步是了解您在开发过程中可能经常使用的微服务设计实践。

1. 每个服务一个数据表
数据库是微服务架构中最重要的组件之一,但开发人员在构建服务时忽视每个服务数据库模式的情况并不少见。数据库组织会影响应用程序的效率和复杂性。开发人员在确定应用程序的组织架构时可以使用的最常见选项是:

每项服务的专用数据库:
专用于一项服务的数据库无法被其他服务访问。这是从整个端到端业务方面更容易扩展和理解的原因之一。

想象一个场景,您的数据库有不同的需求或访问要求。一项服务拥有的数据可能在很大程度上是相关的,而第二项服务可能更适合由 NoSQL 解决方案提供服务,而第三项服务可能需要矢量数据库。在这种情况下,为每个数据库使用专用服务可以帮助您更轻松地管理它们。

这种结构还减少了耦合,因为一个服务无法将自己绑定到另一个服务的表上。服务被迫通过已发布的接口进行通信。缺点是专用数据库需要针对通信失败事件的故障保护机制。

所有服务共享的单一数据库:
单个共享数据库不是微服务架构的标准,但仍然值得一提作为替代方案。这里的问题是,使用单个共享数据库的微服务失去了开发人员所依赖的许多关键优势,包括可扩展性、稳健性和独立性。

尽管如此,在某些情况下共享物理数据库可能是合适的。然而,当所有服务共享单个数据库时,在其中强制执行逻辑边界非常重要。例如,每个服务都应该拥有自己的架构,并且应该限制读/写访问权限,以确保服务无法探索它们不属于的地方。

2.Saga模式
Saga是一系列本地事务。在微服务应用程序中,传奇模式可以帮助维护分布式事务期间的数据一致性。
saga 模式是其他设计模式的替代解决方案,它通过提供回滚机会来允许多个事务。

一个常见的场景是允许客户使用信用购买产品的电子商务应用程序。数据可能存储在两个不同的数据库中:一个用于订单,另一个用于客户。购买金额不能超过信用额度。要实现 Saga 模式,开发人员可以在两种常见方法之间进行选择。

1.编排Choreography:
使用编排方法,一个服务将执行一个事务,然后发布一个事件。在某些情况下,其他服务会响应这些发布的事件,并根据其编码指令执行任务。根据预设,这些次要任务可能也会发布事件,也可能不会。

2.协调orchestration :
协调方法将使用一个专门的协调者对象来执行事务和发布事件,以编排事件,触发其他服务通过完成其任务来做出响应。协调者告诉参与者要执行哪些本地事务。

Saga 是一种复杂的设计模式,需要高水平的技能才能成功实施。不过,正确实施的好处是可以在多个服务之间保持数据一致性,而不会出现紧密耦合的情况。

3.API网关模式
对于具有多个客户端的大型应用程序,实现 API 网关模式是一个引人注目的选择。最大的好处之一是它使客户端无需了解服务是如何分区的。然而,不同的团队会出于不同的原因重视 API 网关模式。其中一个可能的原因是它通过充当客户端应用程序和服务之间的反向代理为一组微服务授予单个入口点。另一个是客户端不需要知道服务是如何划分的,并且服务边界可以独立发展,因为客户端对它们一无所知。

客户也不需要知道如何查找大量不断变化的服务或与之通信。您还可以为特定类型的客户端(例如,前端的后端)创建网关,这可以改善人体工程学并减少获取数据所需的往返次数。此外,API 网关模式可以处理身份验证、SSL 终止和缓存等关键任务,这使您的应用程序更加安全且用户友好。

另一个优点是该模式使客户端无需了解服务是如何分区的。在进入下一个模式之前,还有一个好处需要介绍:安全性。该模式提高安全性的主要方式是减少攻击面。通过提供单一入口点,API 端点不会直接暴露给客户端,并且可以有效地实施授权和 SSL。

开发人员可以使用此设计模式将内部微服务与客户端应用程序解耦,以便可以利用部分失败的请求。这可确保整个请求不会因为单个微服务无响应而失败。为此,编码的 API 网关利用缓存提供空响应或返回有效的错误代码。

4.聚合器设计模式
聚合器设计模式用于从各种微服务收集数据片段并返回聚合以进行处理。虽然与后端到前端 (BFF) 设计模式类似,但聚合器更通用,没有明确用于 UI。

为了完成任务,聚合器模式接收请求并根据分配的任务向多个服务发送请求。一旦每个服务都响应了请求,此设计模式就会组合结果并启动对原始请求的响应。

5. 断路器 设计模式
此模式通常应用于同步通信的服务之间。当服务表现出高延迟或完全无响应时,开发人员可能会决定使用断路器。这里的实用性是,当单个微服务无响应时,可以防止跨多个系统发生故障。因此,调用不会堆积并使用系统资源,这可能会导致应用程序内出现严重延迟,甚至导致一系列服务故障。

将此模式作为断路器设计中的函数来实现需要调用一个对象来监视故障情况。当检测到故障情况时,断路器将跳闸。一旦触发,所有对断路器的调用都将导致错误并被定向到不同的服务。或者,调用可能会导致检索默认错误消息。
开发人员应该注意断路器模式函数的三种状态。这些都是:

  1. 打开:当故障数量超过阈值时,断路器模式打开。处于这种状态时,微服务会给出调用错误,而不执行所需的功能。
  2. 闭合:当断路器闭合时,处于默认状态,所有呼叫均正常响应。这是开发人员希望断路器微服务保持的理想状态——当然是在一个完美的世界中。
  3. 半开:当断路器检查潜在问题时,它保持半开状态。有些呼叫可能会正常响应,但有些则可能无法正常响应。这取决于断路器最初切换到此状态的原因。

6.命令查询责任分离(CQRS
如果开发人员想要解决数据争用风险等传统数据库问题,则可以使用命令查询责任分离 (CQRS) 设计模式。CQRS 还可以用于应用程序性能和安全性复杂且对象同时暴露于读取和写入事务的情况。
其工作方式是 CQRS 负责更改实体的状态或返回事务中的结果。可以提供多个视图用于查询目的,并且系统的读取侧可以与写入侧分开优化。这种转变可以通过单独查询模型和命令来降低所有应用程序的复杂性,以便:

  • 模型的写入端处理持久性事件并充当读取端的数据源
  • 模型的读取端生成数据的投影,这是高度非规范化的视图

7. 异步消息传递
如果服务不需要等待响应并且可以在故障后继续运行其代码,则可以使用异步 消息传递。使用这种设计模式,微服务可以以快速且响应迅速的方式进行通信。有时这种模式被称为事件驱动的通信。

为了实现速度最快、响应速度最快的应用程序,开发人员可以使用消息队列 来最大限度地提高效率,同时最大限度地减少响应延迟。此模式可以帮助连接多个微服务,而无需创建依赖项或将它们紧密耦合。尽管异步通信需要做出权衡(例如最终一致性),但它仍然是一种灵活、可扩展的设计微服务架构的方法。

8. 事件溯源
当开发人员想要捕获实体状态的所有更改时,在微服务中使用事件溯源 设计模式。使用 Kafka 等事件存储或替代方案将有助于跟踪事件更改,甚至可以充当消息代理。消息代理有助于不同微服务之间的通信、监控消息并确保通信可靠稳定。为了促进此功能,事件源模式存储一系列状态更改事件,并且可以通过重放实体的发生来重建当前状态。

当事务对应用程序至关重要时,使用事件源是微服务中的一个可行选择。当需要避免对现有数据层代码库进行更改时,这也很有效。

9.扼杀者
开发人员主要使用strangler  设计模式将单体应用程序逐步转换为微服务。这是通过用新服务替换旧功能来实现的——因此,这就是该模式的名称。一旦新服务准备好执行,旧服务就会被“扼杀”,以便新服务可以接管。

为了成功实现从整体架构到微服务的转移,开发人员使用外观接口,允许他们公开单独的服务和功能。目标功能从整体中脱离出来,因此可以“扼杀”和替换它们。

要充分理解这种特定模式,了解整体应用程序与微服务的不同之处会很有帮助。

10. 分解模式
分解设计模式用于将整体应用程序分解为更小、更易于管理的微服务。开发人员可以通过以下三种方式之一实现此目的:

1、按业务能力分解:
许多企业拥有不止一种业务能力。例如,电子商务商店可能具有管理产品目录、库存、订单和交付等功能。过去,单个整体应用程序可能已用于每项服务,但举例来说,企业决定创建一个微服务应用程序来管理这些未来的服务。在这种常见场景中,企业可能会选择使用按业务能力进行分解。

当应用程序具有大量相互关联的功能或进程时,可以使用此功能。当功能或流程可能频繁更改时,开发人员也可以使用它。好处是拥有更集中、更小的服务可以实现更快的迭代和实验。

2、按子域分解:
这非常适合使用大量业务逻辑的异常大型和复杂的应用程序。例如,如果应用程序使用多个工作流程、数据模型和独立模型,您可以使用此功能。将应用程序分解为子域有助于更轻松地管理代码库,同时促进更快的开发和部署。一个易于掌握的示例是托管在单独子域(例如 blog.companyname.com)上的博客。这种方法可以将博客与根域的业务逻辑分开。

3、按交易分解:
对于跨多个组件或服务的许多事务操作来说,这是一种合适的模式。当有严格的一致性要求时,开发人员可以选择此选项。例如,考虑提交保险索赔的情况。索赔请求可能同时与客户应用程序和索赔微服务交互。

总之
利用设计模式使组织更易于管理,设置正确的架构和流程工具将帮助您创建成功的微服务工作流程。使用上述设计模式并在我们的博客中了解有关微服务的更多信息,以创建强大的功能应用程序。