就像很难用一个绝对的方式去判断架构的好坏一样,在大多数情况下,我们也很难以外部视角去判断微服务拆分粒度的合理性,需要对上下文非常了解才能作出一个相对合理的评价,比如 团队规模多大, 代码规模多大, 有没有平台化, 有没有工具链, 是否需要持续交付/交付速度要求, 团队文化如何等等。
我认为,最基本的是要做到网络IO、CPU效率的优化,其次是团队规模、交付速度的考量,然后才做其他的考量。
微服务设计原则
垂直划分优先原则
应该根据业务领域对服务进行垂直划分,因为水平划分可能会导致:
- 服务之间调用次数更多,性能大幅度下降。
- 实现一个功能要跨越更多的服务,沟通成本增加。
垂直划分,让团队能关注业务实现。
持续演进原则
服务数量在非必要的情况下,应该逐步划分,持续演进,避免服务数量的爆炸性增长。类似灰度发布,减少故障影响范围。
服务自治、接口隔离原则
尽量消除服务对其他服务的强依赖,这样可以减少沟通成本,提升服务稳定性。
服务通过标准的接口隔离,隐藏内部实现细节,让服务能够独立开发、测试、部署和运行。
服务应该遵循职责单一、闭包(更新服务的时候,不需要去更新其他服务的代码)的原则。
自动化驱动原则
部署和运维的成本会随着服务的增多呈现指数级的增长,每个服务都需要部署、监控、日志分析等运维工作,成本会显著提升。
在服务划分之前,应该首先构建自动化的工具级环境。微服务架构基于自动化的工具链,以流水交付的方式串联整个DevOps流程。
微服务划分方法
当业务复杂度足够高的时候,应该基于领域驱动来划分服务。而DDD本身足够复杂,很多概念比较抽象,所以当业务复杂度比较低的时候,可以选择基于数据驱动划分服务。
基于数据驱动划分服务
数据驱动强调的是数据结构,也就是通过分析需求,来确定整体数据结构,根据表之间的关系划分服务。
一般步骤如下:
- 需求分析。通过领域专家确定目标,然后总结User Story,确定核心的业务流程;通过工具呈现比较粗糙的页面,进行内部讨论;不断迭代此环节,直到满意为止。
- 抽象数据结构。根据需求总结User Case,协助分析需求,从中抽象数据结构。
- 划分服务。分析数据结构,识别服务——服务应该满足高内聚、低耦合、单一职责、闭包。
- 确定服务之间的调用关系。分析主要流程,然后根据流程确定服务调用关系,如果出现问题需要回到步骤1。
- 业务流程验证。重新回到User Story,以服务为粒度实现时序图,此阶段重点在于验证服务划分是否合适,需要关注如下问题:一次请求如果跨越多个服务,那么一致性的要求是什么;跨服务查询是否有必要;性能和成本问题。
基于领域驱动划分服务
领域驱动强调业务的实现效果,通过和领域专家不断交流,确定关键业务场景,逐步确定边界上下文。
一般步骤如下:
- 通过模型和领域专家建立统一语言。建立统一语言是为了更深入的理解需求,通用语言尽量以业务语言为主,而非技术语言;通用语言与代码一样,需要不断的重构。
- 业务分析。确定核心的业务流程,然后逐步扩展到全部。最好通过工具呈现比较粗糙的界面,供内部讨论。
- 寻找聚合。显示的定义领域模型的边界。
- 确定服务调用关系。先分析出主要流程,根据一次请求需要调用的服务来确定服务调用关系。
- 业务流程验证。以服务为粒度实现时序图,也需要关注如下问题:一次请求如果跨越多个服务,那么一致性的要求是什么;跨服务查询是否有必要;性能和成本问题。
从已有单体架构中逐步划分服务
绝大多数场景都是从单体架构开始,随着业务的发展拆分为微服务。
一般都是在单体里提取公共服务基础部分,以垂直划分优先,可以参考从平台到中台:企业IT架构转型之道。