单体服务-微服务拆分基本准则

服务拆分基本准则

拆分服务的合理性
1、一个小功能的修改从需求到上线需要多长时间?正常情况下的微服务架构交付周期应该是以天为单位的。如果一个小功能的修改需要几周到几个月的时间,可能意味着服务划分粒度过大,存在太多的冲突,要等待合并代码。
2、 大多数功能修改是否可以在一个服务内完成?如果经常需要跨服务团队的联合开发组才能完成一个新功能的开发或者旧功能的修改,则说明服务划分存在问题。
3、是否要频繁修改接口?频繁修改接口有可能是接口设计不合理导致的,也有可能是服务划分的问题导致的,说明服务之间的边界并不是特别明确和稳定。
4、 响应时间是否能满足要求?在某些追求极致性能的场景中,对响应时间要求较高,服务划分的层次太多、粒度太小都可能导致响应时间不能满足要求。
5、 是否存在大量的跨服务更新?是否存在大量的跨服务的关联查询?出现这两个问题,可能是因为划分不合理。

拆分服务方式
1、先拆分业务代码再拆分数据库。数据库并没有拆分,只是从单体中抽象出部分服务。当业务逐步稳定后再彻底进行数据迁移。注意,处于过渡阶段时数据库并没有彻底分离,一切依赖都通过接口访问。但是这只是口头上的约定,对于业务开发人员直接在数据库中进行关联查询。需要通过Code Review的方式避免。服务划分是一个长期的过程,需要积累大量的领域知识,以此来理解核心流程。最好是和领域专家一起组成联合团队,在理解核心问题的情况下,持续拆分服务并验证拆分合理性,随着时间的推移,还可以重新划分。可见,服务拆分是一个持续性的过程。
2、业务代码和数据库同步拆分,部分业务服务被拆分出来的同时,数据库也被同步拆分出来。 根据服务将数据库彻底拆分为多个独立的数据库,每个服务独享数据库服务,服务之间只能通过接口调用。这看起来非常美好,但需要为此做大量的数据迁移。当业务处于初期,需求不是非常确定,开发人员对业务理解不是特别透彻的时候,可能拆分后发现拆分得并不合理,只能再进行合并,又要进行一次数据迁移。相对来说,业务代码拆分成本更低,而数据迁移的成本更高,频繁、大量的数据迁移并不可取。

拆分模式
1、基于领域驱动划分服务
领域驱动是一个自上而下的架构设计方法,通过和领域专家建立统一的语言,不断交流,确定关键业务场景,逐步确定边界上下文。领域驱动更强调业务实现效果,认为自下而上的设计可能会导致技术人员不能更好地理解业务方向,进而偏离业务目标。
通常基于领域驱动划分服务的步骤如下。
(1)通过模型和领域专家建立统一语言。建立统一语言是为了更深入地理解需求。通用语言尽量以业务语言为主,而非技术语言;通用语言和代码一样,需要不断地重构。
(2)业务分析。确定核心的业务流程,然后逐步扩展到全部。最好通过工具呈现比较粗糙的界面,供内部讨论。
(3)寻找聚合。显式地定义领域模型的边界。最近比较热门的事件风暴,是一种基于领域驱动分析业务、划分服务的方法。
事件风暴就是把所有的关键参与者都召集到一个很宽敞的屋子里来开会,并且使用便利贴来描述系统中发生的事情,如图2-5所示。
(4)确定服务调用关系。先分析出主要流程,根据一次请求需要调用的服务来确定服务调用关系。如果存在水平划分,则需要根据服务依赖原则确定关系。如果存在问题,则需要回到(1)重新开始。
(5)业务流程验证。以服务为粒度实现时序图,注意此阶段重点是要验证服务划分是否合适,主要关注如下问题。
· 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。
· 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。
· 性能是否能满足要求。
· 成本是否满足要求。
(6)持续优化。

2、基于数据驱动划分服务

数据驱动是一个自下而上的架构设计方法,数据驱动强调的是数据结构,也就是通过分析需求,确定整体数据结构,根据表之间的关系划分服务。

通常基于数据驱动划分服务的步骤如下。
(1)需求分析。通过领域专家(或者产品经理)确定目标,然后总结User Story,确定核心的业务流程;通过工具呈现比较粗糙的界面,进行内部讨论;不断迭代此环节,直到满意为止。
(2)抽象数据结构。根据需求总结Use Case,协助分析需求,从中抽象数据结构。
(3)划分服务。分析数据结构,识别服务——服务应该满足高内聚、低耦合、单一职责等特征。
(4)确定服务调用关系。先分析出主要流程,根据请求需要调用的服务确定服务调用关系。如果存在问题,则需要回到(1)重新开始。
(5)业务流程验证。重新回到User Story,以服务为粒度实现时序图,注意此阶段重点是验证服务划分是否合适,要关注如下问题。
· 一次更新操作如果要跨越更多服务,那么一致性的要求是什么。
· 跨服务查询时,是否要做关联查询,一个服务内是否能解决问题。
· 性能是否能满足要求。
· 成本是否满足要求。
(6)持续优化。

3、从已有单体架构中逐步划分服务
在大多数场景下,并非从开始阶段就采用微服务架构,而是随着业务不断发展,从最初的单体架构中逐步拆分服务。下面描述了从一个单体架构逐步拆分的步骤。
(1)所有微服务拆分都是从一个单体架构太大,需要被拆散开始。我们应该从单体架构开始,当系统规模足够大、团队人数足够多时,再逐步拆分服务,通常前后端分离是拆分的第一步。
(2)提取公共基础服务,如单点登录。拆分可以遵循逻辑分离和物理分离两种方法。另外随着系统压力的增加,可能会用到消息中间件、分布式缓存等服务。
(3)不断地从老系统中抽象出服务,垂直划分优先。
(4)当业务越来越复杂的时候,API Gateway做了太多的事情,会成为一个瓶颈点,服务之间的依赖关系也会变得越来越复杂,此时,需要适当地进行水平扩展。

拆分原则

拆分的大原则是一块业务不依赖或极少依赖其它服务,有独立的业务语义,为超过两个的其他服务或客户端提供数据,那它就应该被拆分成一个独立的服务模块。单体演变SOA 也好、微服务也好,解决的根本问题都是团队分工与系统性能问题。

1、垂直划分优先。企业应该根据业务领域对服务进行垂直划分
2、单一职责、高内聚低耦合(简单来说一张表划分一个服务)
3、 服务粒度适中(有的团队甚至一个接口一个服务)
4、考虑团队结构
5、演进式拆分(随着迭代不断进行优化)
6、服务自治,接口隔离,避免项目之间双向依赖

尽量消除对其他服务的强依赖,这样可以降低沟通成本,提升服务稳定性。服务通过标准的接口隔离,隐藏内部实现细节。这样可以让服务保持独立开发、测试、部署、运行,以服务为单位持续交付。

7、按照功能的重要程度进行拆分

不同业务的公司均有不同的核心业务,例如P2P的核心业务肯定是标的、投标、出借、回款、电商主业务流程肯定是商品、用户购买、购物车、下单业务线为主业务线。所以要根据不同公司不同核心业务拆分、重要的核心业务甚至可以进行更细粒度的拆分、例如订单、订单附属信息等。

8、自动化驱动

部署和运维的成本会随着服务的增多呈指数级增长,每个服务都需要部署、监控、日志分析等运维工作,成本会显著提升。因此,在服务划分之前,应该首先构建自动化的工具及环境。开发人员应该以自动化为驱动力,简化服务在创建、开发、测试、部署、运维上的重复性工作,通过工具实现更可靠的操作,避免微服务数量增多带来的开发、管理复杂度问题。

拆分策略

1、比较独立的新业务优先采用微服务架构。从成本角度考虑,新业务采用新的架构是最合理的,因为这样做对老业务的影响最小。
2、优先抽象通用服务。因为通常通用服务的边界比较明显,耦合度低,比较容易分离。
3、 优先抽象比较容易识别的、边界比较明显的服务。如果原有包结构比较清晰,可以基于原有包结构中有明显边界的、比较完整的业务进行划分,这是从成本角度考虑。如果已经基于单体架构开发了一段时间,对业务的理解程度已经非常高,那么开发及架构人员能够比较容易地提炼出一些边界比较明显的服务。
4、优先抽象核心服务。因为微服务的开发及运维成本比较高,并不是所有的地方都需要划分很小的粒度。往往一些比较边缘的运营、管理的系统甚至不会考虑拆分。另外,随着时间的推移,有一些业务可能会发生改变,因此应该先抽象出核心服务。
5、优先抽象具有独立属性的服务。应根据功能的变更频率、资源占用、技术栈等属性划分服务。

你可能感兴趣的:(微服务,microservices)