微服务划分模式
虽然服务是逐步被拆分出来的,随着业务的演进,在某一时刻,可能需要我们重新审视服务划分得是否合理。本节向大家推荐两种服务划分的方法,首先介绍如何选择服务划分的方法。
基于业务复杂度选择服务划分方法
根据业务复杂度划分服务,如图2-4所示。当业务复杂度足够高的时候,应该基于领域驱动划分服务,而领域驱动本身足够复杂,很多概念比较抽象,应用范围并不是特别广泛,所以当业务复杂度较低时,可以选择基于数据驱动划分服务。数据驱动更容易理解和上手。也就是说,除非业务复杂度非常高,否则应该优先以数据驱动划分服务。这里的业务复杂度专指业务逻辑,而非数据量、并发量等相关复杂度。
在做出选择的时候,还有一个参考指标是,团队以前是否已经基于领域驱动开发业务。也就是说,如果产品已经基于领域驱动开发了一段时间,团队具备了领域驱动开发的能力,那么推荐继续选择领域驱动划分服务。如果是一个全新的产品,则可以灵活选择。
选择服务划分的方法时要重点考虑如下条件。
· 业务复杂度。
· 团队对领域驱动的熟悉程度。
基于数据驱动划分服务
数据驱动是一个自下而上的架构设计方法,数据驱动强调的是数据结构,也就是通过分析需求,确定整体数据结构,根据表之间的关系划分服务。
通常基于数据驱动划分服务的步骤如下。
(1)需求分析。通过领域专家(或者产品经理)确定目标,然后总结User Story,确定核心的业务流程;通过工具呈现比较粗糙的界面,进行内部讨论;不断迭代此环节,直到满意为止。
(2)抽象数据结构。根据需求总结Use Case,协助分析需求,从中抽象数据结构。
(3)划分服务。分析数据结构,识别服务——服务应该满足高内聚、低耦合、单一职责等特征。
(4)确定服务调用关系。先分析出主要流程,根据请求需要调用的服务确定服务调用关系。如果存在问题,则需要回到(1)重新开始。
(5)业务流程验证。重新回到User Story,以服务为粒度实现时序图,注意此阶段重点是验证服务划分是否合适,要关注如下问题。
· 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。
· 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。
· 性能是否能满足要求。
· 成本是否满足要求。
(6)持续优化。
基于领域驱动划分服务
领域驱动是一个自上而下的架构设计方法,通过和领域专家建立统一的语言,不断交流,确定关键业务场景,逐步确定边界上下文。领域驱动更强调业务实现效果,认为自下而上的设计可能会导致技术人员不能更好地理解业务方向,进而偏离业务目标。
通常基于领域驱动划分服务的步骤如下。
(1)通过模型和领域专家建立统一语言。建立统一语言是为了更深入地理解需求。通用语言尽量以业务语言为主,而非技术语言;通用语言和代码一样,需要不断地重构。
(2)业务分析。确定核心的业务流程,然后逐步扩展到全部。最好通过工具呈现比较粗糙的界面,供内部讨论。
(3)寻找聚合。显式地定义领域模型的边界。最近比较热门的事件风暴,是一种基于领域驱动分析业务、划分服务的方法。
事件风暴就是把所有的关键参与者都召集到一个很宽敞的屋子里来开会,并且使用便利贴来描述系统中发生的事情,如图2-5所示。
· 用桔黄色的便利贴代表领域事件,在上面用一句话描述曾经发生过什么事情。
· 用蓝色的便利贴代表命令。命令的发起者可能是人,也可能是注入系统中的外部事件,或者定时器等。
· 用黄色的便利贴代表聚合。聚合是一组相关领域对象的集合,高内聚、低耦合是其基本要求,聚合内还要保证数据一致性。
(4)确定服务调用关系。先分析出主要流程,根据一次请求需要调用的服务来确定服务调用关系。如果存在水平划分,则需要根据服务依赖原则确定关系。如果存在问题,则需要回到(1)重新开始。
(5)业务流程验证。以服务为粒度实现时序图,注意此阶段重点是要验证服务划分是否合适,主要关注如下问题。
· 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。
· 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。
· 性能是否能满足要求。
· 成本是否满足要求。
(6)持续优化。
从已有单体架构中逐步划分服务
在大多数场景下,并非从开始阶段就采用微服务架构,而是随着业务不断发展,从最初的单体架构中逐步拆分服务。下面描述了从一个单体架构逐步拆分的步骤。
(1)所有微服务成功的故事都是从一个单体架构太大,需要被拆散开始的,如图2-6所示。我们应该从单体架构开始,当系统规模足够大、团队人数足够多时,再逐步拆分服务,通常前后端分离是拆分的第一步。
(4)当业务越来越复杂的时候,API Gateway做了太多的事情,会成为一个瓶颈点,服务之间的依赖关系也会变得越来越复杂,此时,需要适当地进行水平切分,如图2-8所示。