微服务的分解和组合模式
使用微服务架构划分服务和团队是微服务架构实施的重要一步,良好的划分和拆分是使系统达到松耦合和高内聚的效果,然后通过微服务的灵活组装可以满足上层各种各样的业务处理需求。
在微服务架构的需求分析和架构设计过程中,通常是用领域的动词和名词来划分微服务的。例如,对于一个电商后台系统,可以分解为订单、商品、商品目录、库存、购物车、交易、支付、发票、物流等子系统,每个名词和动词都可以是一个微服务,将这几个微服务组合在一起,就实现了电商平台用户购买商品的整个业务流。
这样拆分以后,系统具有敏捷性、灵活性、可伸缩性等,拆分后有多个高度自治的微服务,可以按照以下几种方式组合微服务。
服务代理模式
服务代理模式是最简单的服务组合模式,它根据业务的需求选择调用后端的某个服务。在返回给使用端之前,代理可以选择性地对后端服务的输出进行加工。
服务代理模式的架构如下图所示:
服务聚合模式
服务聚合模式是最常用的服务组合模式,它根据业务流程处理的需要,以一定的顺序调用依赖的多个微服务,对依赖的微服务返回的数据进行组合、加工和转换,最后以一定的形式返回给使用方。
这里每个被依赖的微服务都有自己的缓存和数据库,聚合服务本身可以有自己的数据存储,包括缓存和数据库等,也可以是简单的聚合,不需要持久化任何数据。
服务聚合模式的架构如下图所示:
这里体现了DRY(Don’t Repeat Yourself)原则的设计理念,在设计或者构造应用时,最大限度地重用了现有的实现。
这样的设计原则有如下的好处:
- 三个独立的子服务可以各自独立开发、敏捷变更和部署
- 聚合服务封装下层的业务处理服务,由三个独立的子服务完成数据持久化等工作,项目结构清晰明了
- 三个独立的子服务对于其他使用方仍然可以重用
服务串联模式
服务串联模式类似于一个工作流,最前面的服务1负责接收请求和响应使用方,串联服务后再与服务1交互,随后服务1与服务2交互,最后从服务2产生的结果经过服务1和串联服务逐个处理后返回给使用方。
串联模式的架构如下图所示:
服务串联模式之间的调用通常使用同步的RESTFul风格的远程调用实现,注意,这种模式采用的是同步调用的方式,在串联服务还没有完成并返回之前,所有服务都会阻塞和等待,一个请求会占用一个线程来处理,因此,在这种模式下不建议服务的层级太多,如果能用服务聚合模式代替,则优先使用服务聚合模式,而不是使用这种服务串联模式。
相对于服务聚合模式,服务串联模式有一个优点,即串联链路上再增加一个节点时,只要不是在串联服务的正后面增加,那么串联服务是无感知的。
服务分支模式
服务分支模式是服务代理模式、服务聚合模式和服务串联模式相结合的产物。分支服务可以拥有自己的数据库存储,电泳多个后端的服务或者服务串联链,然后将结果进行组合处理再返回给客户端。分支服务也可以使用代理模式,简单地调用后端的某个服务或者服务链,然后将返回的数据直接返回给使用方。
分支模式的架构如下图所示:
分支模式会方法服务间的依赖关系,因此在显示的微服务设计中尽量保持服务调用级别的简单,在使用服务组合和服务代理模式时,不要使用服务串联模式和服务分支模式,以保持服务依赖关系的清晰明了,这也减少了日后维护的工作量。
服务异步消息模式
前面所有服务组合模式都使用同步的RESTFul风格的同步调用来实现,同步调用模式在调用的过程中会阻塞线程,如果服务提供方迟迟没有返回,则服务消费方会一直阻塞,在严重情况下会撑满服务的线程池,出现雪崩效应。
因此在构建微服务架构时,通常会梳理核心系统的最小化服务集合,这些核心的系统服务使用同步调用,而其他核心链路以外的服务可以使用异步消息队列进行异步化。
服务异步消息模式的架构如下图所示:
服务共享数据模式
服务共享数据模式其实是反模式。由于去掉了数据共享,所以仅通过服务之间良好定义的接口进行交互和通信,使得每个服务都是自治的。
服务共享模式的架构如下图所示:
单元化架构
一些平台由于对性能有较高的要求,所以采用微服务化将服务进行拆分,通过网络服务进行通信,尽管网络通信的带宽已经很宽, 但还是会有性能方面的损耗,在这种场景下,可以让不同的微服务共享一些资源,例如:缓存、数据库等,甚至可以将缓存和数据在物理拓扑上和微服务部署字啊一个物理机中,最大限度减少网络通行带来的性能损耗,我们将这种方法为“单元化架构”。
单元化架构如下图所示:
遗留的整体服务
对于历史遗留的传统单体服务,我们在重构微服务的过程中,发现单体服务依赖的数据表耦合在一起,对其拆分需要进行反规范化的处理,可能会造成数据一致性问题,在没有完全理解和有把握的前提下,会选择保持现状,让不同的微服务暂时共享数据存储。
除了上面提到的两个场景,任何场景都不能使用服务数据共享模式。