读书笔记:微服务架构设计模式

2022-08-24

Microservice Patterns

https://book.douban.com/subject/26989027

  • 是什么(What):
    • 一套围绕微服务拆分、通信、数据一致性、查询、测试、部署和可观测性的模式语言,用可组合的模式解决分布式业务系统中的重复问题
  • 为什么(Why):
    • 微服务用独立部署和团队自治换取交付速度,却把单体内部的调用与事务变成不可靠的网络通信和跨服务协作;必须同时理解每个模式解决的问题与引入的代价
  • 怎么做(How):
    • 先按业务能力或子域确定边界,再逐项处理 API、数据所有权、事务、查询、故障和运维;从模块化单体渐进演化,不要先拆服务再寻找边界

核心观点:

微服务架构不是把应用切成许多进程,而是让一组围绕业务能力组织、拥有自己数据的服务可以独立开发、测试、部署和扩展。模式的价值不在于提供标准答案,而在于把问题、上下文、方案和后果一起呈现。

  • 微服务以分布式复杂性换取独立交付能力
    • 服务可独立部署、扩展和由小团队端到端拥有,但网络故障、跨服务事务、查询、测试和运维都会更复杂
    • 只有独立交付和组织并行带来的收益超过这些成本时,微服务才值得采用
  • 服务边界应围绕业务能力,并以数据所有权落实
    • 按业务能力或 DDD 子域拆分,让一起变化的行为与数据留在同一服务内
    • 每个服务拥有自己的数据;共享数据库会把 schema 变成隐式公共 API,使服务无法真正独立部署
  • 通信模式的选择,本质上是在选择耦合和失败方式
    • 同步调用直观但引入时间与可用性耦合;异步消息降低运行时耦合,却必须处理重复、乱序、积压和最终一致性
    • API 和事件都是长期契约,应隐藏内部模型并保持兼容演进
  • 分布式数据问题需要一组相互配合的模式
    • Saga 用一系列本地事务与补偿动作维护跨服务业务一致性,但不提供事务隔离
    • Transactional Outbox 解决业务写入与消息发送的原子性,幂等消费者处理至少一次投递,API Composition 或 CQRS 解决跨服务查询
  • 微服务必须由自动化和渐进式演进支撑
    • 超时、熔断、限流、契约测试、日志、指标和追踪都是架构的一部分,而不是上线后的补丁
    • 从模块化单体出发,以 Strangler Application 逐步抽取服务;验收标准是能否独立变更、部署和回滚,而不是服务数量

启发点(关键洞察):

  1. 独立部署才是服务边界的试金石:如果发布一个服务仍需协调多个团队、同时升级多个服务或共享数据库迁移,它只是物理上分开,逻辑上仍是单体
  2. 数据所有权决定真实边界:代码可以轻易拆仓库,数据依赖却最难切断;绕过 API 读写他人数据库会重新建立最强耦合
  3. Saga 首先是业务建模问题:应先定义哪些步骤可补偿、哪些不可逆、失败后业务处于什么状态,再选择协同或编排
  4. 事件同时是事实和契约:发布者只能陈述已经发生的事实,不能假设消费者行为;事件 schema 的兼容性应像 API 一样被治理
  5. 异步不等于无耦合:它消除了时间耦合,却保留语义和 schema 耦合,还引入顺序、重复与延迟问题
  6. 可观测性是分布式系统的控制面:无法关联一次请求、一次 Saga 和相关消息,就无法可靠诊断部分失败
  7. 模式应成组使用:Database per Service 会引出 Saga、Outbox、CQRS 和契约测试;选择一个模式时,也是在接受它带来的后续问题
  8. 微服务是组织和技术的共同设计:若团队结构、所有权和发布流程不随边界调整,架构不会带来自治

行动:

  1. 拆分前画出业务能力、限界上下文、数据所有权和团队所有权,检查四者是否大体对齐
  2. 为每个跨服务流程写出成功路径、超时、重复、乱序、补偿失败和人工介入路径,再决定通信方式
  3. 所有写数据库 + 发消息场景默认评估 Transactional Outbox;所有消息消费者默认设计幂等
  4. 为同步调用设置超时、并发上限和失败策略,限制请求链长度,不做无边界重试
  5. 用消费者驱动契约测试保护服务接口,把端到端测试限制在少数关键用户旅程
  6. 把 trace ID、业务 ID、message ID 和 Saga ID 纳入统一关联规范,确保日志、指标和追踪可以互相跳转
  7. 每次拆分后用能否独立开发、测试、部署、回滚验收;若仍需联动发布,继续消除耦合而不是继续切小
  8. 优先从模块化单体开始,只有在组织规模、独立扩展或交付瓶颈提供明确收益时才支付分布式成本

金句:

  1. 微服务架构的本质不是服务足够小,而是服务能够围绕业务能力独立演进。
  2. 每个服务拥有自己的数据,是自治的基础,也是分布式数据复杂性的来源。
  3. 补偿不是回滚历史,而是用新的业务事实抵消旧事实的影响。
  4. 网络越过进程边界后,失败、延迟、重复和乱序就必须成为正常控制流的一部分。
  5. 模式不是银弹;一个模式解决当前问题时,往往会制造下一个需要显式处理的问题。
  1. https://microservices.io/patterns
  2. https://www.oreilly.com/library/view/microservices-patterns/9781617294549/
  3. https://www.manning.com/books/microservices-patterns

评论