背景
您正在开发服务器端企业应用程序。它必须支持各种不同的客户端,包括桌面浏览器,移动浏览器和本机移动应用程序。该应用程序还可能会公开供第三方使用的API。它还可以通过Web服务或消息代理与其他应用程序集成。应用程序通过执行业务逻辑来处理请求(HTTP请求和消息);访问数据库;与其他系统交换消息;并返回HTML / JSON / XML响应。存在与应用程序的不同功能区域相对应的逻辑组件。
问题
应用程序的部署架构是什么?
现状和诉求
- 有一组开发人员正在处理该应用程序
- 新团队成员必须迅速提高工作效率
- 应用程序必须易于理解和修改
- 您希望实践应用程序的持续部署
- 您必须在多台计算机上运行该应用程序的多个副本,以满足可伸缩性和可用性要求
- 您想利用新兴技术(框架,编程语言等)
解决办法
定义一个体系结构,将应用程序构建为一组松散耦合的协作服务。该方法对应于Scale Cube的Y轴。每个服务都实现了一组狭义的相关功能。例如,应用程序可能包含订单管理服务,客户管理服务等服务。
服务使用HTTP / REST等同步协议或AMQP等异步协议进行通信。可以彼此独立地开发和部署服务。每个服务都有自己的数据库,以便与其他服务分离。使用Saga模式维护服务之间的数据一致性。
例子
让我们假设您正在构建一个电子商务应用程序,该应用程序接收来自客户的订单,验证库存和可用信用,并运送它们。该应用程序包含几个组件,包括实现用户界面的StoreFrontUI,以及用于检查信用,维护库存和装运订单的一些后端服务。该应用程序包含一组服务。
结果背景
优点
该解决方案具有许多优点:
1 支持大型复杂应用程序的持续交付和部署。
- 更好的可测试性 - 测试服务更小,速度更快
- 更好的可部署性 - 可以独立部署服务
- 它使您能够围绕多个自动团队组织开发工作。它使您能够围绕多个团队组织开发工作。每个(两个披萨)团队拥有并负责一项或多项单项服务。每个团队都可以独立于所有其他团队开发,部署和扩展他们的服务。
2 每个微服务都相对较小
- 开发人员更容易理解
- IDE可以更快地提高开发人员的工作效率
- 应用程序启动速度更快,这使开发人员的工作效率更高,并加快了部署速度
3 改善了故障隔离。例如,如果一个服务中存在内存泄漏,则只会影响该服务。其他服务将继续处理请求。相比之下,单片架构中的一个行为不当的组件可能会导致整个系统崩溃。
4 消除对技术堆栈的任何长期承诺。在开发新服务时,您可以选择新的技术堆栈。同样,在对现有服务进行重大更改时,您可以使用新技术堆栈重写它。
缺点
该解决方案有许多缺点:
1 开发人员必须处理创建分布式系统的额外复杂性。
- 开发人员工具/ IDE面向构建单一应用程序,并不为开发分布式应用程序提供明确支持。
- 测试更加困难
- 开发人员必须实现跨服务通信机制。
- 实现跨越多个服务而不使用分布式事务的用例很困难
- 实现跨多个服务的用例需要团队之间的仔细协调
2 部署复杂性。在生产中,还存在部署和管理由许多不同服务类型组成的系统的操作复杂性。
3 增加内存消耗。微服务架构用NxM服务实例替换N个单片应用程序实例。如果每个服务都在自己的JVM(或等效服务器)中运行,这通常是隔离实例所必需的,那么就会产生M倍运行时M次的开销。此外,如果每个服务在其自己的VM(例如EC2实例)上运行,如Netflix的情况,则开销甚至更高。
注意点
1 何时使用微服务架构?
使用这种方法的一个挑战是决定何时使用它。在开发应用程序的第一个版本时,您通常不会遇到此方法所解决的问题。此外,使用精心设计的分布式架构将减缓开发速度。这对于初创公司来说可能是一个主要问题,其最大的挑战通常是如何快速发展业务模型和随附的应用程序。使用Y轴拆分可能会使快速迭代变得更加困难。然而,稍后,当挑战是如何扩展并且您需要使用功能分解时,纠结的依赖关系可能使您难以将单片应用程序分解为一组服务。
2 如何将应用程序分解为服务?
另一个挑战是决定如何将系统划分为微服务。这是一门艺术,但有许多策略可以提供帮助:
- 按业务能力分解并定义与业务功能相对应的服务。
- 通过域驱动设计子域进行分解。
- 通过动词或用例分解并定义负责特定操作的服务。例如运送服务,负责发送完整订单。
- 通过定义一个服务来分解名词或资源,该服务负责给定类型的实体/资源上的所有操作。例如负责管理用户帐户的帐户服务。
- 理想情况下,每项服务应该只有一小部分职责。 (叔叔)Bob Martin谈论使用单一责任原则(SRP)设计课程。 SRP将类的责任定义为改变的原因,并声明类只应有一个改变的理由。将SRP应用于服务设计也是有意义的。
理想情况下,每项服务应该只有一小部分职责。 (叔叔)Bob Martin谈论使用单一责任原则(SRP)设计课程。 SRP将类的责任定义为改变的原因,并声明类只应有一个改变的理由。将SRP应用于服务设计也是有意义的。
另一个有助于服务设计的类比是Unix实用程序的设计。 Unix提供了大量的实用程序,如grep,cat和find。每个实用程序都完成一件事,通常非常好,并且可以使用shell脚本与其他实用程序结合执行复杂的任务。
3 如何保持数据一致性?
为了确保松散耦合,每个服务都有自己的数据库。维护服务之间的数据一致性是一项挑战,因为2阶段提交/分布式事务不是许多应用程序的选项。应用程序必须改为使用Saga模式。服务在其数据更改时发布事件。其他服务使用该事件并更新其数据。有几种方法可靠地更新数据和发布事件,包括事件采购和事务日志拖尾。
4 如何实现查询?
另一个挑战是实现需要检索多个服务所拥有的数据的查询。
API组合和命令查询责任隔离(CQRS)模式。
相关模式
有许多与微服务模式相关的模式。单片架构是微服务架构的替代品。其他模式解决了在应用微服务架构时将遇到的问题。
1 分解模式
- 按业务能力分解
- 按子域分解
2 每个服务数据库模式描述了每个服务如何拥有自己的数据库以确保松散耦合。
3 API网关模式定义了客户端如何在微服务架构中访问服务。
4 客户端发现和服务器端发现模式用于将客户端的请求路由到微服务架构中的可用服务实例。
5 消息传递和远程过程调用模式是服务可以通信的两种不同方式。
6 每个主机的单个服务和每个主机的多个服务模式是两种不同的部署策略。
7 横切关注模式:微服务机箱模式和外部化配置
8 测试模式:服务组件测试和服务集成合同测试
9 断路器
10 访问令牌
11 可观察性模式:
- 日志聚合
- 应用指标
- 审核日志记录
- 分布式跟踪
- 异常跟踪
- 健康检查API
- 记录部署和更改
12 UI模式:
- 服务器端页面片段组成
- 客户端UI组合
已知案例
大多数大型网站,包括Netflix,亚马逊和eBay,已经从单片架构演变为微服务架构。
Netflix是一种非常流行的视频流服务,负责高达30%的互联网流量,拥有大规模,面向服务的架构。他们每天处理来自800多种不同设备的视频流API的超过10亿次呼叫。每个API调用都会向平均六次调用后端服务。
Amazon.com最初有两层架构。为了扩展,他们迁移到由数百个后端服务组成的面向服务的体系结构。有几个应用程序调用这些服务,包括实现Amazon.com网站和Web服务API的应用程序。 Amazon.com网站应用程序调用100-150服务来获取用于构建网页的数据。
拍卖网站ebay.com也从单片架构演变为面向服务的架构。应用程序层由多个独立的应用程序组成。每个应用程序都实现特定功能区域的业务逻辑,例如购买或销售。每个应用程序都使用X轴分割,一些应用程序(如搜索使用Z轴分割)。 Ebay.com还将X,Y和Z样式缩放的组合应用于数据库层。
使用微服务架构的公司还有许多其他例子。