作者:李艳鹏,“云时代架构”技术社区创始人,著有《分布式服务架构:原理、设计与实战》,现任某知名支付平台架构组负责人,曾在花旗银行、甲骨文、路透社、新浪微博等大型IT互联网公司担任技术负责人和架构师,现专注于大规模高并发的线上和线下支付平台的应用架构和技术架构的规划与落地,负责交易、支付、渠道、出款、风控、对账等核心支付系统的设计与实现,在移动支付、聚合支付、合规账户、扫码支付、标记化支付等业务场景上有产品应用架构规划与落地的实践经验。文末赠送李艳鹏先生参与编写的新书《可伸缩服务架构:框架与中间件》

0.题记

使用微服务架构划分服务和团队是微服务架构实施的重要一步,良好的划分和拆分使系统达到松耦合和高内聚的效果,然后通过微服务的灵活组装可以满足上层的各种各样的业务处理需求。

在微服务架构的需求分析和架构设计过程中,通常是用领域的动词和名词来划分微服务的,例如,对于一个电商后台系统,可以分解为订单、商品、商品目录、库存、购物车、交易、支付、发票、物流等子系统,每个名词和动词都可以是一个微服务,将这几个微服务组合在一起,就实现了电商平台用户购买商品的整个业务流。

这样拆分以后,系统具有敏捷性、灵活性、可伸缩性等,拆分后有多个高度自治的微服务,那么以什么方式组合微服务呢?

1. 服务代理模式

服务代理模式是最简单的服务组合模式,它根据业务的需求选择调用后端的某个服务。在返回给使用端之前,代理可以对后端服务的输出进行加工,也可以直接把后端服务的返回结果返回给使用端。

服务代理模式的架构如图1-12所示。

图1-12

在笔者工作的微服务化架构平台下,经常会使用这种模式,典型的案例是做平滑的系统迁移,通常经历如下4个阶段。

  • 在新老系统上双写。

  • 迁移双写之前的历史遗留数据。

  • 将读请求切换到新系统。

  • 下调双写逻辑,只写新系统。

服务代理模式常常应用到第3步,一般会对读请求切换设计一个开关,开关打开时查询新系统,开关关闭时查询老系统。

迁移案例中开关的逻辑如图1-13所示。

图1-13
2. 服务聚合模式

服务聚合模式是最常用的服务组合模式,它根据业务流程处理的需要,以一定的顺序调用依赖的多个微服务,对依赖的微服务返回的数据进行组合、加工和转换,最后以一定的形式返回给使用方。

这里,每个被依赖的微服务都有自己的缓存和数据库,聚合服务本身可以有自己的数据存储,包括缓存和数据库等,也可以是简单的聚合,不需要持久化任何数据。

服务聚合模式的架构如图1-14所示。

图1-14

这里体现了DRY(Don’t Repeat Yourself)原则的设计理念,在设计或者构造应用时,最大限度地重用了现有的实现。假如一块业务逻辑由三个独立的逻辑块组成,每个独立的逻辑块可能有多个使用方,则DRY原则推荐将三个独立的逻辑块封装成三个独立运行的微服务,然后使用本节的服务聚合模式开发聚合服务,将三个独立的逻辑块聚合在一起提供给上层组合服务。这样的设计原则有如下好处。

  • 三个独立的子服务可以各自独立开发、敏捷变更和部署。

  • 聚合服务封装下层的业务处理服务,由三个独立的子服务完成数据持久化等工作,项目结构清晰明了。

  • 三个独立的子服务对于其他使用方仍然可以重用。

考虑到本节开头的例子,在对微服务进行拆分时,将电商后台系统大致拆分成订单、商品、商品目录、库存、购物车、交易、支付、发票、物流等微服务,那么电商平台的前端应用就是后端各个微服务的一个最大的聚合服务,前端应用通过调用商品和商品目录显示商品列表,提供给用户选择商品的功能,用户选择商品后增加商品到购物车,在用户从购物车结算时,调用交易系统完成交易和支付等。

电商前台的聚合模式的案例架构如图1-15所示。

图1-15

另外,聚合服务也可以是一个纯后台服务,通过聚合对使用方输出组合的服务,例如在上面的电商系统案例中,在用户选择结算后,系统调用交易,交易系统会调用库存系统锁库存,然后创建交易订单,引导用户去支付,支付成功后扣减库存,最后通过发票服务开具电子发票。

电商后台交易服务的聚合模式架构如图1-16所示。

图1-16
3. 服务串联模式

服务串联模式类似于一个工作流,最前面的服务1负责接收请求和响应使用方,串联服务后再与服务1交互,随后服务1与服务2交互,最后,从服务2产生的结果经过服务1和串联服务逐个处理后返回给使用方,如图1-17所示。

图1-17

服务串联模式之间的调用通常使用同步的RESTful风格的远程调用实现,注意,这种模式采用的是同步调用方式,在串联服务没有完成并返回之前,所有服务都会阻塞和等待,一个请求会占用一个线程来处理,因此在这种模式下不建议服务的层级太多,如果能用服务聚合模式代替,则优先使用服务聚合模式,而不是使用这种服务串联模式。

相对于服务聚合模式,服务串联模式有一个优点,即串联链路上再增加一个节点时,只要不是在串联服务的正后面增加,那么串联服务是无感知的。

在串联服务中调用链的最后端增加服务无感知的架构如图1-18所示。

图1-18

在上面提及的电商案例中,UI前端应用调用交易,交易调用商品库存系统锁定库存和扣减库存,使用的就是服务串联模式。

服务串联模式案例的架构如图1-19所示。

图1-19
4. 服务分支模式

服务分支模式是服务代理模式、服务聚合模式和服务串联模式相结合的产物。

分支服务可以拥有自己的数据库存储,调用多个后端的服务或者服务串联链,然后将结果进行组合处理再返回给客户端。分支服务也可以使用代理模式,简单地调用后端的某个服务或者服务链,然后将返回的数据直接返回给使用方。

服务分支模式的架构如图1-20所示。

图1-20

在实际的业务平台建设中,由于业务的复杂性,抽象的微服务可能有多层的依赖关系,依赖关系并不会太简单,经常呈现树形的分支结构。

以电商平台的支付服务架构为例,如图1-21所示。

图1-21

支付服务对接两个外部的支付网关,都要经过各自的支付渠道网关,同时支持账户余额支付,这个支付服务其实就是一个分支模式,在实际项目中这种服务分支模式很多。

笔者在构建支付平台时,由于大量地使用了服务分支模式,所以发现了一个比较有趣的现象,如下所述。

假设有一个基础服务,在服务分支模式的多个层次中对基础服务都有依赖,那么当基础服务的一台机器宕机时,假设基础服务有8台机器,则最后受影响的流量并不是1/8。假设基础服务6共有8台机器,服务1、服务3和服务5组成某服务的一个调用链,则调用链过程中会多次调用基础服务6。

具体服务的调用链示意图如图1-22所示。

图1-22

某天,基础服务6的8台机器中的1台宕机,按照常理,大家都认为只影响其中1/8的流量,而统计结果显示影响的业务结果竟然大于1/8。

仔细思考,造成这个结果的原因是调用链上有多个层次重复调用了基础服务,导致基础服务挂掉时影响的流量有累加效果,具体计算如下。

假设进入系统的流量为n,调用链从服务3开始调用服务6,服务3有1/8的流量失败,这时剩下的成功的流量为7/8 ×n,剩下的成功的流量继续走到服务5,服务5再次调用服务6,又有1/8的流量失败,剩下7/8 × 7/8× n。

假设基础服务资源池中的机器个数为i,一次挂掉的机器个数为j,一个调用链中调用x次基础服务,那么正确处理的流量的计算公式为:

假设允许的可用性波动率为a,求出底层服务一次宕机1台时最少应该配置的机器数为:

对公式进行转换:

由于一次只允许一台机器宕机:

所以得出需要设置的机器数量i为:

对于上面的案例,每次最多允许基础服务6宕机1台,在这种情况下需要保持可用性的波动率小于25%,一共有两层服务依赖基础服务6,通过上述公式计算得出:

i > 7.5

结果,至少为服务6部署9台机器,这样在1台机器宕机时,对可用性的波动性影响控制在25%以内。

由于分支模式放大了服务的依赖关系,因此在现实的微服务设计中尽量保持服务调用级别的简单,在使用服务组合和服务代理模式时,不要使用服务串联模式和服务分支模式,以保持服务依赖关系的清晰明了,这也减少了日后维护的工作量。

5. 服务异步消息模式

前面的所有服务组合模式都使用同步的RESTful风格的同步调用来实现,同步调用模式在调用的过程中会阻塞线程,如果服务提供方迟迟没有返回,则服务消费方会一直阻塞,在严重情况下会撑满服务的线程池,出现雪崩效应。

因此,在构建微服务架构系统时,通常会梳理核心系统的最小化服务集合,这些核心的系统服务使用同步调用,而其他核心链路以外的服务可以使用异步消息队列进行异步化。

服务异步消息模式的架构如图1-23所示。

图1-23

在图1-23中,聚合服务同步调用服务1和服务2,而服务2通过消息队列将异步消息传递给服务3和服务4。

典型的案例就是在电商系统中,交易完成后向物流系统发起消息通知,通知物流系统发货,如图1-24所示。

图1-24
6. 服务共享数据模式

服务共享数据模式其实是反模式,在1.3.3节中提出了去数据共享模式,由于去掉了数据共享,所以仅仅通过服务之间良好定义的接口进行交互和通信,使得每个服务都是自治的,服务本身和服务的团队包含全角色栈的技术和运营人员,这些人都是专业的人做专业的事,使沟通在团队内部解决,因此可以使效率最大化。

服务共享数据模式的架构如图1-25所示。

图1-25

然而,在下面两种场景下,我们仍然需要数据共享模式。

  • 单元化架构

一些平台由于对性能有较高的要求,所以采用微服务化将服务进行拆分,通过网络服务进行通信,尽管网络通信的带宽已经很宽,但是还会有性能方面的损耗,在这种场景下,可以让不同的微服务共享一些资源,例如:缓存、数据库等,甚至可以将缓存和数据在物理拓扑上与微服务部署在一个物理机中,最大限度地减少网络通信带来的性能损耗,我们将这种方法称为“单元化架构”。

单元化架构的示意图如图1-26所示。

图1-26

  • 遗留的整体服务

对于历史遗留的传统单体服务,我们在重构微服务的过程中,发现单体服务依赖的数据库表耦合在一起,对其拆分需要进行反规范化的处理,可能会造成数据一致性问题,在没有对其完全理解和有把握的前提下,会选择保持现状,让不同的微服务暂时共享数据存储。

7,赠书

感谢博文视点出版社大力赞助!本次赠书无上限,最低赠送两位数!看小伙伴的热情度!最高可送出一千本!仍然没有抢到该怎么办?看图书封面右下角!

如何获取?方式一:参与评论,看眼熟度获赠!方式二:加入架构师小秘圈微信社群,群内领红包,手气最佳可得赠书!我该怎么加入架构师小秘圈微信社群? 看最下面!已经加入的,切勿重复入群!

推荐阅读:

技术:分布式唯一ID极简教程

职场:程序员职业规划

分享:2T架构师学习资料干货分享

觉得有帮助?请转发给更多人!

架构师小秘圈,聚集10万架构师的小圈子!不定期分享技术干货,行业秘闻!汇集各类奇妙好玩的话题和流行动向!长按左侧图片,扫码加入架构师微信群!

微服务的分解和组合-文末赠书相关推荐

  1. 云计算监控—Prometheus监控系统(文末赠书)

    陈金窗 刘政委 张其栋 郑少斌 读完需要 20 分钟 速读仅需 7 分钟 本文摘自于<Prometheus 监控技术与实战>一书,从云计算时代的业务特点出发,探讨了云计算监控的目标和挑战, ...

  2. 神理论 | 我面向淘宝编程,而你面向什么编程?(文末赠书5本)

    神理论 | 我面向淘宝编程,而你面向什么编程? 陌生人一定会疑问,嵌入式跟taobao有半毛钱关系啊?那么本文,博主就跟你聊聊,如何面向淘宝学习嵌入式! 文章目录 1 写在前面 2 面向XXX编程 3 ...

  3. 【好书推荐:第5期】数据产品经理:实战进阶(文末赠书)

    最近很多小伙伴都来找居士咨询关于数据产品经理相关的问题,而市面上也一直缺少这样专门针对数据产品经理的体系性书籍. 幸好,现在有这样一本书面世了,就是我的好友的新书<数据产品经理:实战进阶> ...

  4. 再来学习一下RT-Thread的软件架构 | 文末赠书5本《软件架构实践》

    再来学习一下RT-Thread的软件架构 摘要: 学习和使用了RT-Thread有2年多了的时间,最近一直在研究开源项目Matter相关的软件架构设计,趁此机会,再来温习一下rt-thread的软件架 ...

  5. PyTorch自然语言处理入门与实战 | 文末赠书

    文末赠书 注:本文选自人民邮电出版社出版的<PyTorch自然语言处理入门与实战>一书,略有改动.经出版社授权刊登于此. 处理中文与英文的一个显著区别是中文的词之间缺乏明确的分隔符.分词是 ...

  6. 利用excel与Pandas完成实现数据透视表(文末赠书)

         文末赠书 数据透视表是一种分类汇总数据的方法.本文章将会介绍如何用Pandas完成数据透视表的制作和常用操作. 1,制作数据透视表 制作数据透视表的时候,要确定这几个部分:行字段.列字段.数 ...

  7. 文末赠书3本 | 盼了一年的Core Java最新版卷Ⅱ,终于上市了

    文章目录 盼了一年的Core Java最新版卷Ⅱ,终于上市了! Core Java基于Java 17全面升级 Core Java最新版卷Ⅱ现已上市 卷Ⅰ.卷Ⅱ有何不同? 如何阅读<Java核心技 ...

  8. 【福利赠书】有人说,测试驱动开发已死?(文末赠书3本)

     友情推荐一本测试领域的教科书:(文末送3本) < 测试驱动开发:入门.实战与进阶>,英文原书名为<Learning Test-Driven Development >,是一本 ...

  9. 替代VBA!用Python轻松实现Excel编程(文末赠书)

    大家好,我是小z,也可以叫我阿粥~ 面向Excel数据处理自动化的脚本编程,目前主要有VBA和Python两种语言可供选择. 从上世纪90年代到目前,VBA一直是Excel脚本编程的主要工具.VBA语 ...

最新文章

  1. Direct2D开发:Direct2D 和 GDI 互操作性概述
  2. 菜鸟教程python3-Python3 简介
  3. 31 天重构学习笔记28. 为布尔方法命名
  4. 笔记-高项案例题-2018年上-质量管理
  5. 【PAT甲级 十进制转十三进制】1027 Colors in Mars (20 分) Java版 5/5通过
  6. HHKB Programming Contest 2020 总结
  7. 413 Request Entity Too Large 异常记录
  8. i++,++i 作为参数
  9. 【机器人学】正运动学详解
  10. python中英文时间转换
  11. Django创建APP
  12. mysql 交换分区吗_MySQL分区表——交换分区
  13. 必备算法基础——神经网络
  14. 并行编程,绝不是你想的那么简单
  15. python3 pymysql库介绍
  16. 【计算机组成原理】寻址方式
  17. python批量检索文献_基于Python的文献检索系统设计与实现
  18. ThinkPHP模版引擎之变量输出具体解释
  19. Pivoting跳板攻击
  20. 5u fb库 三菱plc_三菱PLCFX5U系列

热门文章

  1. python利用requests进行爬虫_Python利用Requests库写爬虫(一)
  2. UVA122 树的层次遍历 Trees on the level(两种方法详解)
  3. G - Shuffle‘m Up POJ - 3087
  4. A-棋盘问题(dfs)
  5. oracle12 java_java – 无法使用12c jar创建Eclipse数据源到Oracle 12c.不过11g的作品
  6. 初识Redux-Saga
  7. MacOS 下使用 intellij IDEA 将git上传项目到 Github
  8. 浅谈进程同步和互斥的概念
  9. 物联网的编年史1974-2025 你都知道多少?
  10. 1,html常用标签学习