面试官:微服务如何拆分?需要考虑什么因素?

候选人:一般按照功能拆分

面试官:还有吗?

候选人:唔……

要拆分微服务,首先我们要了解微服务拆了会有什么问题?怎么合理拆服务?

拆分服务会带来什么问题?

举个电商系统下单扣库存的例子。

对于单体应用,通讯在进程内部进行,下单方法调用扣库存方法,有问题就回滚事务,利用数据库同一个Session会话的ACID特性干活,保证数据的强一致性,即使在调用下单方法成功后应用崩溃,数据也不会提交到数据库,不会产生脏数据。

而拆分成各个微服务后,代码、数据库进行了隔离,下单扣库存逻辑变成了订单服务通过RPC调用库存服务,由于不受同一个数据库Session会话控制,就必然会存在因业务处理失败、应用崩溃、网络通讯异常等一系列问题导致的数据不一致。

这是一个典型的复杂度转移的例子——单体应用的代码复杂度转移到了微服务之间的通讯复杂度,整体的复杂度并没有降低。

回到经典的分布式CAP定理:数据一致性、可用性、分区容错性,三者取其二。

CAP是分布式系统中三个维度的“客户承诺”:

  • 一致性:要么我给你返回一个错误,要么我给你返回绝对一致的最新数据,强调数据正确

  • 可用性:我一定会给你返回数据,不会给你返回错误,但不保证数据最新,强调的是服务不出错

  • 分区容错性:我会一直运行,不管我的内部出现何种数据同步问题,强调的是不挂掉

为了解决数据一致性问题,业界又引入了各种一致性保障机制,比如BASE理论(基本可用、软状态、最终一致)、分布式事务DTP模型(XA协议、TCC协议)、JTA模型等等,根据对数据一致性的要求又划分为强一致性、弱一致性、最终一致性的方案,在分布式系统中通过一系列措施来保证ACID。

在实际互联网项目开发中,分布式事务不宜设计得太重,通常来说异步的场景使用事务性MQ来解决,比如RabbitMQ、Kafka、RocketMQ等;同步的场景使用业务状态机来规避它们,比如订单分正向销售单、逆向售后单,单据有不同维度的状态,比如支付状态、退款状态、物流状态、开票状态等等,对于出错的环节进行客户干预、系统告警或客服干预,暂时停留在异常节点,这里的“状态”可以理解为BASE理论中的软状态。

说到底还是用BASE理论指导生产。

说那么多,我们通过拆分微服务,提高了系统的分区容错性与可用性,却牺牲了单体应用的一致性优势,所以说,不要为了拆而拆,拆服务也需要合理“动机”,那什么样的“动机”是合理的呢?

如何合理拆分微服务?

OK,了解了服务拆分带来的问题后,我们拆服务就得更加严谨了,那怎么合理拆呢?

这里提供一些思路。

一、按单一职责拆

还是以我们的电商平台举例,一开始我们最核心的OMS订单系统做了特别多事情,包括:用户、下单、商品、库存、出入库、营销……

随着公司业务快速增长,OMS代码激增,新增/修改一个功能就要影响几乎整个链路,稳定性降低,也大大增加了风险,运维变得十分困难,这时不得不把各个模块剥离出来,独立成为UC用户服务、PMS商品服务、CIS中央库存服务、WMS出入库服务、MCS营销中心等等。

我们按照单一职责的划分原则,每一个独立的服务只提供该业务领域的核心功能,继而每个独立的服务演化出更为丰富的功能,数据库也进行垂直拆分提供应用独立访问,并且每个服务提供双节点保证高可用。

二、按团队组织架构拆

这里必须提一提软件架构设计中的第一定律——康威定律。

康威定律是马尔文·康威1967年提出的:“设计系统的架构受制于产生这些设计的组织的沟通结构。”通俗地来讲:产品必然是其(人员)组织沟通结构的缩影。

康威定律可总结为以下四个定律:

第一定律:组织沟通方式会通过系统设计表达出来。

这条定律重点是讲组织架构和沟通对系统设计的影响。

组织的沟通和系统的设计之间紧密相连,特别是复杂系统,解决好人与人的沟通才能有一个更好的系统设计。

沟通的问题会带来系统设计的问题,进而影响整个系统的开发效率和最终产品结果,这也是为什么互联网公司都追求小团队的原因之一。

第二定律:时间再多一件事情也不可能做得完美,但总有时间做完一件事情。

人手永远是不够的,事情永远是做不完的,但可以一件一件来。

这不就是软件行业中“敏捷开发”模式所解决的问题吗,面对这样的状况,敏捷开发可以做到不断迭代、持续交付、快速验证和反馈,并持续改进。

再牛的开发也会写出BUG,再全面的测试覆盖率也无法测出所有的问题,解决方案不是消灭这些问题,是容忍一些问题的存在,然后通过适当的设计(冗余、监控、高可用设计),当问题发生时能够快速解决。

几个开发人员的小公司,去追求微服务、中台架构、这是追求完美吗?

不是,这是找死。

好的架构不是买来的,也不是设计出来的,而是根据业务落地生根长期演化来的。

第三定律:线型系统和线型组织架构间有潜在的异质同态特性。

这一定律是第一定律的具体应用。

想象一下如果公司的架构是这样的:

团队是分布式,每个团队都包含产品、研发、测试、运维等角色,而此时系统是单体应用,那项目沟通和协调的成本是巨大的,弄不好还会打起来。

如果将单块的系统拆分成微服务,每个团队负责自己的部分,对外提供对应的接口即可,互不干扰,系统效率将得到提升,这与软件设计中的高内聚、低耦合是相通的。

直白地说就是想要什么样的系统就搭建什么样的团队,有什么样的团队就搭建什么样的系统,需要前后端分离的系统就搭建前后端分离的团队;反之,拥有前后端分离的团队就可以设计前后端分离的系统。

第四定律:大的系统组织总是比小系统更倾向于分解。

“话说天下大势,分久必合,合久必分。”系统越复杂,越需要增加人手,人手越多,沟通成本也呈指数增长,分而治之便是大多数公司选择的解决方案,分不同的层级,分不同的小团队,让团队内部完成自治理,然后统一对外沟通。

我们试着从康威定律来推导系统的架构演进方向,自然知道微服务的拆解粒度了。

SOA 也好、微服务也好,解决的根本问题是团队分工问题,这是大型软件发展的必然,不因为人的喜好而改变,当你读懂康威定律,就会发现“服务拆分粒度难以准确把握”根本不是本质问题,你有几个 2 pizza 团队,最好就拆成几个微服务。

只有一个开发人员时,尽量就做单体应用,不要没事找刺激拆成 10 个微服务,最终这个开发人员还会把他合成一个。

微服务要求纵向的 2 pizza 团队(无数个小团队,包含开发、测试、运维),如果团队还是处在横向结构的场景下(开发、运维、测试各是一个团队),比如说一些传统大型企业,去实施微服务会让他们很痛苦,尤其是运维团队。

总结一下

具体实践建议:

  • 我们要用一切手段提升沟通效率,比如slack,github,wiki。能2个人讲清楚的事情,就不要拉更多人,每个人每个系统都有明确的分工,出了问题知道马上找谁,避免踢皮球。

  • 通过MVP的方式来设计系统,通过不断地迭代来验证优化,系统应该是弹性设计的。

  • 你想要什么样的系统设计,就架构什么样的团队,能扁平化就扁平化。最好按业务来划分团队,这样能让团队自然的自治内聚,明确的业务边界会减少和外部的沟通成本,每个小团队都对自己的模块的整个生命周期负责,没有边界不清,没有无效的扯皮,inter-operate, not integrate。

  • 做小而美的团队,人多会带来沟通的成本,让效率下降。亚马逊的Bezos有个逗趣的比喻,如果2个披萨不够一个团队吃的,那么这个团队就太大了。事实上一般一个互联网公司小产品的团队差不多就是7,8人左右。

总之,只要说得清楚,运维能力又能跟上,服务拆分一般就是合理的!

有道无术,术可成;有术无道,止于术

欢迎大家关注Java之道公众号

好文章,我在看❤️

面试基操:微服务拆分需要考虑什么因素?相关推荐

  1. 微服务拆分需要考虑的必要因素与坚持原则

    前言:创业公司往往因为有限的时间和投入,把系统所有的功能都聚集在一起.随着业务的不断发展,技术人员开始不断地对架构进行解耦和拆分.微服务在最近几年大行其道,很多公司的研发人员都在考虑微服务架构,或者在 ...

  2. 迭代开发中的微服务拆分

    微服务拆分是微服务架构绕不过的话题,随着架构演进,在迭代开发中拆分微服务有时非常必要,微服务拆分不仅仅是一项技术层面的重构,首先要选择的合适的时机,另外在拆分前一定要理清业务现状,制定好拆分的基本原则 ...

  3. 微服务拆分,选型与演进

    微服务拆分原则 在微服务拆分中,核心需求在于拆开的微服务之间的联系越少越好,数据交互也是越少越好.因为微服务之间的数据一致性非常难处理,如果一致性方面的问题很少,整体做起来就比较简单了. 微服务架构选 ...

  4. 微服务拆分策略和原则

    目录 微服务拆分目的 单体应用拆分成微服务的时机 拆分时指导原则 拆分的粒度把控 微服务拆分策略 微服务合并 拆分过程中要注意事项 注意:本文参考  微服务拆分策略和原则 - 简书 微服务拆分目的 不 ...

  5. 这才是微服务拆分的正确姿势,值得学习!

    作为Java工程师,微服务拆分则是在开发过程发展到一定阶段不得不面对的技术架构要求.大家可能会遇到这些问题:为什么要拆服务?拆解方法有哪些?公司真的这样拆解微服务的吗? 以上问题统统别担心!慕课网特意 ...

  6. 如何使用 DDD 指导微服务拆分?

    点击上方肉眼品世界, 右上角选择"设为星标 深度价值体系传递 开发者在刚开始尝试实现自己的微服务架构时往往会产生一系列问题 : 微服务到底应该怎么划分? 一个典型的微服务到底应该有多微? 如 ...

  7. 微服务拆分时机与原则

    微服务拆分 微服务拆分时机 为了快速迭代 高并发场景 可重用 提交代码经常冲突 小功能要积累到大版本才能上线 服务拆分原则 原则一:高内聚和低耦合. 原则二:服务拆分正交性原则 原则三:服务粒度适中. ...

  8. 现代微服务拆分与设计

    现代微服务拆分与设计 一.AKF扩展立方体 Y轴 X轴 Z轴 二.前后端分离 早期未分离(JSP+Servlet) 半分离 完全分离 三.无状态服务 四.RestFul服务通信 在设计一个微服务的时候 ...

  9. 微服务拆分原则之 AKF

    当我们搭建集群的时候,首先要想明白需要解决哪些问题,搞清楚这个之前,想想单节点.单实例.单机有哪些问题? 单点故障 容量有限 可支持的连接有限(性能不足) ...... 为了解决这些问题,我们需要对服 ...

最新文章

  1. Spark的RDD 文件读取与保存
  2. 处理点云数据 点云与生成前视图
  3. java写龟兔赛跑_简单的实现java多线程——龟兔赛跑
  4. Kubernetes系列之Helm介绍篇
  5. java英文拼写检查并自动纠正
  6. html怎样让列表向下移动,Html无序列表ul控件实现行上下移动.
  7. Daily Report 2012.11.06 刘宇翔
  8. python使用BeautifulSoup的prettify功能来处理HTML文档,之后使用Levenshtein编辑距离计算文档间的相似度
  9. android方法中添加 N,AndroidN(7.0)Settings模块界面加载流程学习
  10. [系统安全] 十二.熊猫烧香病毒IDA和OD逆向分析(上)病毒初始化
  11. RQNOJ愚蠢的矿工
  12. HMC5883L指南针罗盘模块连接arduino使用的注意事项
  13. php 裁剪png图片,解决thinkphp裁剪png图片背景不透明的方法
  14. 做一个有意境的女人难上加难
  15. 微软五笔拼音输入法 86版 v7.2 bt
  16. 老九学堂 学习 C++
  17. 程序员客栈:程序员的经纪人_对于程序员:如何处理干扰和打扰
  18. plsql-数据查询(二、条件查询)
  19. Qt5 编译错误找不到头文件的解决方法
  20. 【mac】QQ截图不能用解决方法

热门文章

  1. Java基础入门笔记-对象的销毁
  2. 文法G[E]分析表分析字符串(i+)-编译原理
  3. 开发文档怎么编写_PoC 编写指南
  4. 界址点圆圈怎么生成_技巧|CASS10.1的界址点圆圈如何变细?
  5. 如何才能成为优秀的测试工程师?
  6. 计算机网络之数据链路层:3、差错控制(奇偶校验、CRC冗余校验、海明校验)
  7. (计算机组成原理)第六章总线-第一节:总线概述(概念,分类,系统总线的结构和性能指标)
  8. 字符串经典题之参数解析
  9. Linux系统编程41:多线程之线程池的概念及实现
  10. 数据结构-线性表之用队列实现栈用栈实现队列