微服务架构和设计模式 - DZone微服务


微服务可以对您的企业产生积极影响。因此,值得了解如何处理微服务架构(MSA)和微服务的一些设计模式以及微服务架构的一般目标或原则。

分解模式
1. 按业务能力分解
微服务是关于使服务松散耦合,应用单一责任原则。它们由业务功能分解,并定义与业务功能相对应的服务。业务能力是业务架构建模的概念。这是企业创造价值的东西。业务能力通常对应于业务对象,例如

  • 订单管理负责订单。
  • 客户管理负责客户。

2.按子域/有界上下文分解
使用业务功能分解应用程序可能是一个良好的开端,但是您会遇到所谓的“上帝类”,它不容易分解。这些类在多个服务中很常见。域驱动设计(DDD)是指应用程序的问题空间 - 业务 - 作为域。域由多个子域组成,每个子域对应于业务的不同部分。
子域名可分为以下几类:
  • 核心 - 业务的关键差异化因素和应用程序中最有价值的部分。
  • 支持 - 与业务有关,但与差异化无关。这些可以在内部实施或外包。
  • 通用 - 不是特定于业务,理想情况下使用现成的软件实现。

订单管理的子域/有界上下文包括:
  • 产品目录服务。
  • 库存管理服务。
  • 订单管理服务。
  • 送货管理服务。

3. 按事务/两阶段提交(2PC)模式分解
您可以通过事务分解服务,然后系统中将有多个事务。分布式事务的重要参与者之一是事务协调器[3]。分布式事务包括两个步骤:
  • 准备阶段 - 在此阶段,交易的所有参与者都准备提交并通知协调员他们已准备好完成交易。
  • 提交或回滚阶段 - 在此阶段,事务协调器向所有参与者发出提交或回滚命令。

2PC的问题在于,与单个微服务的操作的执行时间相比,它非常慢。协调微服务之间的事务,即使它们位于同一网络上,也会降低系统速度,因此这种方法通常不用于高负载情况。

扼杀者模式
上面这三种设计模式在分解绿地应用程序的应用程序时使用,但是你所做的80%的工作是使用大型棕地应用程序单片应用程序(遗留代码库)。扼杀者模式在这里得到了拯救。这将创建两个独立的应用程序,它们在同一URI空间中并排存在。随着时间的推移,新重构的应用程序“扼杀”或替换原始应用程序,直到您最终关闭整体应用程序。Strangler应用程序步骤是转换,共存和消除:

  • 转换 - 使用现代方法创建并行的新站点。
  • 共存 - 将现有站点保留一段时间。从现有站点重定向到新站点,以便逐步实现功能。
  • 消除 - 从现有站点中删除旧功能。

Bulkhead模式
将应用程序的元素隔离到池中,以便在其中一个失败时,其他元素将继续运行。这种模式称为Bulkhead,因为它类似于船体的分段分区。根据用户负载和可用性要求,将分区服务实例拆分为不同的组。此设计有助于隔离故障,并允许您为某些消费者维持服务功能,即使在故障期间也是如此。

边车模式
将应用程序的组件部署到单独的处理器容器中以提供隔离和封装。此模式还可以使应用程序由异构组件和技术组成。这种模式被称为Sidecar,因为它类似于连接到摩托车的边车。在该模式中,边车附加到父应用程序并为应用程序提供支持功能。sidecar还与父应用程序共享相同的生命周期,与父项一起创建和退役。边车模式有时被称为搭档模式。

微服务的集成模式
1.API网关模式
当应用程序分解为较小的微服务时,需要解决一些问题:

  • 不同渠道有多个微服务调用。
  • 需要处理不同类型的协议。
  • 不同的消费者可能需要不同的响应格式。

API网关有助于解决微服务实现引起的许多问题,而不仅限于上述问题。
  • API网关是任何微服务调用的单一入口点。
  • 它可以作为代理服务将请求路由到相关的微服务。
  • 它可以聚合结果以发回给消费者。
  • 此解决方案可以为每种特定类型的客户端创建细粒度的API。
  • 它还可以转换协议请求并进行响应。
  • 它还可以卸载微服务的身份验证/授权职责。

2. 聚合模式
在将业务功能分解为几个较小的逻辑代码片段时,有必要考虑如何协作每个服务返回的数据。这种责任不能留给消费者。聚合器模式有助于解决这个问题。它讨论了我们如何聚合来自不同服务的数据,然后将最终响应发送给消费者。这可以通过两种方式完成:
  1. 复合微服务将调用所有必需的微服务,合并数据,并在发回之前转换数据。
  2. API网关还可以将请求分区为多个微服务,并在将数据发送给消费者之前对其进行聚合。

建议如果要应用任何业务逻辑,则选择复合微服务。否则,API网关是已建立的解决方案。

3.代理模式
我们只是通过API网关公开微服务,API网关有三个API模块:

  • 移动API - 实现FTGO移动客户端的API
  • 浏览器API - 实现在浏览器中运行的JavaScript应用程序的API
  • 公共API - 为第三方开发人员实现API

4. 网关路由模式
API网关负责请求路由。API网关通过将请求路由到相应的服务来实现一些API操作。当它收到请求时,API网关会查询路由映射,该映射指定将请求路由到哪个服务。例如,路由映射可以将HTTP方法和路径映射到服务的HTTP URL。此功能与NGINX等Web服务器提供的反向代理功能相同。

链式微服务模式
对于单个服务或微服务将存在多个依赖性,例如:销售微服务具有依赖性产品微服务和订单微服务。链式微服务设计模式将帮助您为您的请求提供综合结果。微服务1收到的请求,然后与微服务-2通信,它可能与微服务-3通信。所有这些服务都是同步调用。

分支模式
微服务可能需要从多个源(包括其他微服务)获取数据。分支微服务模式是聚合器和链设计模式的混合,允许来自两个或更多微服务的同时请求/响应处理。调用的微服务可以是微服务链。Brach模式还可用于根据您的业务需求调用不同的微服务链或单个链。

客户端UI组合模式
当通过分解业务能力/子域来开发服务时,负责用户体验的服务必须从几个微服务中提取数据。在整体世界中,过去只有一次从UI到后端服务的调用来检索所有数据并刷新/提交UI页面。但现在,它将不一样。使用微服务,UI必须设计为具有屏幕/页面的多个部分/区域的骨架。每个部分都会调用一个单独的后端微服务来提取数据。像AngularJS和ReactJS这样的框架有助于轻松完成。这些屏幕称为单页应用程序(SPA)。每个团队都开发了一个客户端UI组件,例如AngularJS指令,它实现了服务的页面/屏幕区域。

数据库模式
定义微服务的数据库架构,我们需要考虑以下几点:

  • 服务必须松散耦合。它们可以独立开发,部署和扩展。
  • 业务事务可以强制执行跨多个服务的不变量。
  • 某些业务事务需要查询由多个服务拥有的数据。
  • 有时必须复制数据库并按比例共享。
  • 不同的服务有不同的数据存储要求。

1.每个服务一个数据库
为了解决上述问题,必须设计每个微服务一个数据库; 它必须仅对该服务是私有的。它应该仅由微服务API访问。其他服务无法直接访问它。例如,对于关系数据库,我们可以使用每服务私有表,每服务模式或每服务数据库服务器。

2.每个服务共享数据库
我们已经讨论过每个服务一个数据库是微服务的理想选择。它是微服务的反模式。如果应用程序是一个整体,并试图打破微服务,非规范化并不那么容易。每个服务的共享数据库并不理想,但这是可行的解决方案。大多数人认为这是微服务的反模式,但对于棕色应用程序,这是将应用程序分解为更小的逻辑部分的良好开端。这不应该适用于绿地应用。

3.命令查询责任分离(CQRS)
一旦我们实现了每服务数据库,就需要进行查询,这需要来自多个服务的联合数据。这是不可能的。CQRS建议将应用程序分为两部分 - 命令端和查询端。

  • 命令端处理创建,更新和删除请求。
  • 查询端使用实例化视图处理查询部分。

事件源模式通常与其一起使用,以创建任何数据更改的事件。通过订阅事件流来保持物化视图的更新。

4.事件溯源
大多数应用程序使用数据,典型的方法是让应用程序保持当前状态。例如,在传统的创建,读取,更新和删除(CRUD)模型中,典型的数据过程是从商店读取数据。它包含锁定数据的限制,通常使用事务。
Event Sourcing模式定义了一种处理由一系列事件驱动的数据操作的方法,每个事件都记录在一个仅附加存储中。应用程序代码发送一系列事件,这些事件强制性地将数据上发生的每个操作描述到事件存储中,并保存在事件存储中。每个事件代表一组对数据的更改(例如AddedItemToOrder)。
事件存储在充当记录系统的事件存储中。事件存储发布的事件的典型用途是在应用程序中的操作更改它们以及与外部系统集成时维护实体的物化视图。例如,系统可以维护用于填充UI部分的所有客户订单的物化视图。当应用程序添加新订单,添加或删除订单上的项目并添加送货信息时,可以处理描述这些更改的事件并使用它们来更新实体化视图。

5.Saga模式
当每个服务都有自己的数据库并且业务事务跨越多个服务时,我们如何确保跨服务的数据一致性?每个请求都有一个在请求失败时执行的补偿请求。它可以通过两种方式实现:

  • Choreography  - 没有中央协调器,每个服务产生并监听另一个服务的事件并决定是否应该采取行动。编排是一种指定两方或多方的方式; 其中任何一方都无法控制其他方的流程,或者可能对这些流程有任何可见性 - 可以协调其活动和流程以共享信息和价值。当需要跨控制/可见性域协调时,请使用编排。在简单的场景中,您可以将编排想象为网络协议。它规定了各方之间可接受的请求和响应模式。
  • Orchestration - 一个中央协调器orchestrator(对象)负责saga的决策制定和业务逻辑排序。当你控制进程中的所有actor时。当他们都在一个控制领域,你可以控制活动的流程。当然,这通常是在您指定将在您可以控制的一个组织内部制定的业务流程时。

观察模式
1.日志聚合
考虑一个应用程序由多个服务组成的用例。请求通常跨越多个服务实例。每个服务实例都以标准化格式生成日志文件。我们需要一个集中式日志记录服务来聚合来自每个服务实例的日志。用户可以搜索和分析日志。他们可以配置在日志中显示某些消息时触发的警报。例如,PCF确实有一个Log聚合器,它从PCF平台的每个组件(路由器,控制器,Diego等)以及应用程序收集日志。AWS Cloud Watch也是如此。

2.性能指标
当服务组合由于微服务架构而增加时,监视事务变得至关重要,以便可以监视模式并在问题发生时发送警报。
需要度量服务来收集有关各个操作的统计信息。它应聚合应用程序服务的度量标准,该服务提供报告和警报。聚合指标有两种模型:

  • 推送 - 服务将指标推送到指标服务,例如NewRelic,AppDynamics
  • 拉 - 指标服务从服务中提取指标,例如Prometheus

3. 分布式跟踪
在微服务架构中,请求通常跨越多个服务。每个服务通过跨多个服务执行一个或多个操作来处​​理请求。在进行故障排除时,值得拥有跟踪ID,我们会端到端跟踪请求。
解决方案是引入一个事务ID,可以使用以下方法;

  • 为每个外部请求分配唯一的外部请求ID。
  • 将外部请求ID传递给所有服务。
  • 在所有日志消息中包含外部请求ID。

4.健康检查
当实施微服务架构时,服务可能会启动但无法处理事务。每个服务都需要有一个端点,可用于检查应用程序的运行状况,例如运行状况。此API应检查主机的状态,与其他服务/基础结构的连接以及任何特定逻辑。

跨领域关注模式
1. 外部配置
服务通常也会调用其他服务和数据库。对于dev,QA,UAT,prod等每个环境,端点URL或某些配置属性可能不同。任何这些属性的更改都可能需要重新构建和重新部署服务。
为避免代码修改,可以使用配置。外部化所有配置,包括端点URL和凭据。应用程序应在启动时或动态加载它们。这些可以在启动时由应用程序访问,也可以在不重新启动服务器的情况下刷新。

2. 服务发现模式
当微服务出现时,我们需要解决一些关于呼叫服务的问题。
使用容器技术,IP地址可动态分配给服务实例。每次地址更改时,消费者服务都可能中断并需要手动更改。
每个服务URL都必须由消费者记住并紧密耦合。
需要创建一个服务注册表,它将保留每个生产者服务和规范的元数据。服务实例应在启动时注册到注册表,并在关闭时注销。有两种类型的服务发现:

  • 客户端:例如:Netflix Eureka
  • 服务器端:例如:AWS ALB。

3. 断路器模式
服务通常调用其他服务来检索数据,并且下游服务可能会关闭。这有两个问题:首先,请求将继续执行下行服务,耗尽网络资源并降低性能。其次,用户体验将是糟糕且不可预测的。
消费者应该通过代理来调用远程服务,代理的行为类似于电路断路器。当连续故障的数量超过阈值时,断路器跳闸,并且在超时时间段内,所有调用远程服务的尝试都将立即失败。超时到期后,断路器允许有限数量的测试请求通过。如果这些请求成功,则断路器恢复正常操作。否则,如果发生故障,则超时时间再次开始。此模式适用于阻止应用程序尝试调用远程服务或访问共享资源(如果此操作很可能失败)。


蓝绿部署模式
使用微服务架构,一个应用程序可以拥有许多微服务。如果我们停止所有服务然后部署增强版本,停机时间将会很长并且会影响业务。此外,回滚将是一场噩梦。蓝绿色部署模式避免了这种情况。
可以实施蓝绿部署策略以减少或消除停机时间。它通过运行两个相同的生产环境Blue和Green来实现这一目标。我们假设Green是现有的实例,Blue是应用程序的新版本。在任何时候,只有一个环境是实时的,实时环境为所有生产流量提供服务。所有云平台都提供了实施蓝绿部署的选项。