一、逃离单体地狱
1、系统初期,单体应用架构优势
- 应用开发简单(单个项目模块,IDE和开发工具只需要构建一个应用程序)
- 易于对应用程序进行大规模整改
- 测试相对简单直观
- 部署简单
-
2、程序逐渐壮大,系统陷入单体地狱

开发:系统复杂度高。所有代码耦合在同一个项目中,增加了开发者的学习成本、开发成本。
- 提交:单一代码库,导致了额外的沟通成本和协调成本,多分支开发和合并的考虑。
- 编译:开发速度缓慢。即使对代码做非常小的更改,也要对整个项目进行编译构建。
- 部署:同一代码库共用流水线,部署的频率需要协调和控制。
- 启动:启动时编译速度,以及启动时如果有部分变更导致启动失败,会拖慢整个项目的测试进度。
- 故障不隔离:当某一个模块代码造成内存泄露时,会影响整个系统的稳定性,甚至造成整个系统的宕机。
- 技术栈更新困难。
最终结果是软件的质量稳定性降低,软件交付效率降低。
3、拯救之道—微服务架构
应用程序的三维扩展模型:
(1)X轴扩展:在多个实例之间实现请求的负载均衡。可以提高应用程序吞吐量和可用性。这种扩展方式有一个缺点那就是每一个单独的应用服务都有可能访问所有的数据,所以内存中不得不缓存更多的数据来高效的响应。
(2)Z轴扩展:根据请求的属性路由请求。基于多个实例,路由器使用请求中的特定属性将请求路由到适当的实例。这种扩展方式类似于X轴扩展,不同的是Z轴扩展只负责处理一部分数据。
优点举例:每个分区只处理一部分数据,如果请求使用到了本地缓存,那么可以提高缓存的使用率。
缺点:系统复杂性提高。
(3)Y轴扩展:根据功能把应用拆分为服务。X轴扩展和Z轴扩展都有效提升了应用的吞吐量和可用性,但是并不能解决日益增长的开发问题和应用复杂性。Y轴扩展把一个单体应用分成一组服务。
每项服务负责特定的功能。每个服务是一组专注的、内聚的功能职责组成。 每个服务是松耦合的,有自己的私有数据库,通过 API 通信。每个服务可以独立开发,部署,测试和扩展。
4、微服务的优缺点

优点:
- 持续交付和部署
- 容易维护
- 独立部署,扩展
- 团队自治
- 实现和采纳新技术
- 更好的容错性
缺点:
- 服务拆分和定义是一项挑战。
- 分布式系统带来的各种复杂性。(服务的注册发现、数据一致性问题等等)
- 跨服务开发需要协调多个团队。服务部署可能要按照依赖关系排序 (有些需求开发需要协调多个团队进行评估、握手)
什么阶段使用微服务?初创公司几乎都是从单体应用开始(微服务架构设计需要时间成本,在公司初创时更应该考虑系统的功能需求)
5、使用模式语言来进行架构决策
模式是针对特定上下文中发生的问题的可重用解决方案。模式语言是解决特定领域内问题的相关模式的集合。
(1)常用的模式结构包括:需求:必须解决的问题和围绕这个问题的特定上下文环境。优先级排序
- 结果上下文:好处,弊端,问题。
- 相关模式:前导;后续,替代;泛化;特化
(2)以微服务模式为例:
需求:系统架构
结果上下文:
好处:持续交付、部署、总体更稳定。
弊端:分布式系统复杂性
问题:服务的拆分、数据一致性等等问题
相关模式:模式之间的关系
前导:催生这个模式的需求的模式。 (微服务模式是其他模式的前导模式)
后续:后续模式是解决当前模式引入的新问题的模式。(比如微服务模式引发的服务拆分问题等等,会催生一些需求,这些需求的解决方案就是微服务模式的后续模式)
替代:同一需求的不同解决方案 (替代模式:单体模式和微服务模式互为替代模式)
泛化:针对问题的一般性解决方案
特化:针对特定模式的具体解决方案
(3)针对特定领域的模式的集合组成模式语言,微服务架构模式语言是微服务相互关联的软件架构设计和设计模式的集合。
服务拆分相关模式:
根据哪种方式来进行服务分解
- 根据业务能力分解,围绕业务功能组织服务
- 根据子域分解,子域围绕领域驱动设计(DDD)来组织服务
通信相关模式:
微服务架构构建的应用程序为分布式系统,需要考虑服务与服务之间的通信模式以及服务与外部的通信模式。
- 通信风格:使用哪一种进程间通信方式
- 服务发现:服务调用方如何发现服务提供方的ip+port
- 可靠性:服务提供方有实例异常时,服务调用方如何实现异常重试。注册中心挂掉时,如何保证服务直接仍旧可以正常调用
- 事务性:分布式事务问题。
- 外部 API:客户端调用系统
部署模式:
通过命令行或者界面部署和管理服务。部署平台往往基于虚拟机,容器。
可观测性:
- 健康检查 API 进行服务探活
- 日志聚合: 集中式日志服务器来检索和触发报警
- 分布式追踪:为外部请求分配唯一 ID,用于各个服务之间追踪
- 异常跟踪:skywalking等组件实现异常请求的链路追踪
- 应用指标:指标服务器
自动化测试相关模式、安全相关模式等等。
二、服务的拆分策略
1、定义应用程序架构的三步式流程
(1)应用程序需求提炼为关键请求。系统操作是应用程序必须处理的请求的一种抽象描述。它既可以是更新数据的命令,也可以是检索数据的查询
(2)第二步是确定如何分解服务。通过业务能力分解或通过领域驱动设计分解。
(3)定义服务API和协作方式。确定每个服务的API
2、识别系统操作
- 创建抽象领域模型,这些关键类提供了用于系统操作的词汇表
- 定义系统操作
3、根据业务能力进行服务拆分
组织的业务能力通常是指这个组织的业务是做什么,它们通常都是稳定的。与之相反,组织采用何种方式来实现它的业务能力,是随着时间不断变化的。
某些顶级能力(如会计记账能力)将映射到服务。在其他情况下,子能力映射到服务。
4、根据子域进行划分
4、定义服务API
(1)将系统操作分配给服务。
(2)服务提供哪些API,以及这些API之间的协调5、拆分单体应用为服务的难点
(1)网络延迟。 (许多本地调用被替代为远程过程调用)
(2)同步进程间通信导致可用性降低。(下游服务不可用)
(3)分布式事务问题。有些更新操作必须要以原子方式更新。
(4)上帝类阻碍了拆分
