当前位置: 首页 > 科技观察

面试基础:微服务拆分需要考虑哪些因素?

时间:2023-03-21 13:24:50 科技观察

采访者:如何拆分微服务?需要考虑哪些因素?应聘者:一般按功能分面试官:还有吗?考生:嗯……要拆分微服务,首先要了解微服务,拆了会有什么问题?如何合理拆除服务?拆解服务会带来哪些问题?举一个电子商务系统下订单和扣除库存的例子。对于单个应用程序,通信是在进程内进行的。下订单的方法调用了扣除库存的方法。如果出现问题,事务将回滚。利用数据库同会话的ACID特性来保证数据的强一致性,即使在调用订单时也是如此。方法成功后,应用崩溃,数据不会提交到数据库,也不会产生脏数据。拆分成各种微服务后,代码和数据库隔离,下单和扣库存的逻辑就变成了订单服务通过RPC调用库存服务。由于不受同一个数据库会话控制,难免会出现业务处理失败的情况。应用程序崩溃、网络通信异常等一系列问题导致的数据不一致。这是一个典型的复杂度转移的例子——单体应用的代码复杂度转移到了微服务间的通信复杂度上,而整体的复杂度并没有降低。回到经典的分布式CAP定理:数据一致性、可用性、分区容错,三选二。CAP在分布式系统中是三个维度的“客户承诺”:一致性:要么我给你返回错误,要么我给你返回最新的绝对一致的数据,强调数据是正确的。可用性:我一定会给你返回数据,不会给你返回错误,但我不保证数据是最新的,重点是服务没有错误。分区容错:我会一直跑,不管我内部出现什么样的数据同步问题,重点是不挂掉。为了解决数据一致性问题,业界引入了各种一致性保证机制,如BASE理论(基本可用、软状态、最终一致性)、分布式事务DTP模型(XA协议、TCC协议)、JTA模型等.根据对数据一致性的要求,分为强一致性、弱一致性和最终一致性方案,在分布式系统中通过一系列措施来保证ACID。在实际的互联网项目开发中,分布式事务的设计不要太重。一般来说,事务型MQ用于解决异步场景,如RabbitMQ、Kafka、RocketMQ等;同步场景使用业务状态机来规避,比如订单分为正向销售订单和反向售后订单。单据有不同维度的状态,如支付状态、退款状态、物流状态、开票状态等,对于客户介入、系统报警或客服介入错误环节,暂时停留在异常节点,“状态”这里可以理解为BASE理论中的软状态。说到底,还是用BASE理论来指导生产。说了这么多,我们通过拆分微服务提高了系统的分区容忍度和可用性,但是牺牲了单体应用的一致性优势。所以,不要为了分裂而分裂。拆分服务也需要合理的“动机”。那么什么样的“动机”才是合理的呢?如何合理拆分微服务?OK,了解了服务拆分带来的问题后,我们在拆分服务上就要更加严谨了,那么如何合理拆分呢?这里有一些思路。1.按照单一职责拆解以我们的电商平台为例。一开始,我们核心的OMS订单系统做了很多事情,包括:用户、订单、产品、库存、仓储、营销……随着公司业务的快速增长和OMS代码的激增,添加/修改一个功能几乎会影响整个链路,稳定性降低,风险也大大增加。运维变得非常困难。这时候各个模块就得分开独立成为UC用户服务、PMS商品服务、CIS中央库存服务、WMS出入库服务、MCS营销中心等。我们遵循单一职责分工的原则,各自独立服务只提供业务领域的核心功能,然后每个独立的服务演化出更丰富的功能,同时数据库也垂直拆分,提供独立的应用访问,每个服务提供双节点保证高可用。2.按照团队组织结构进行拆迁这里不得不提到软件架构设计中的第一定律——康威定律。康威定律由MarvinConway于1967年提出:“设计系统的架构受制于产生这些设计的组织的沟通结构。”通俗地说:一个产品一定是其(人员)组织沟通结构的缩影。康威定律可以概括为以下四个定律:第一定律:一个组织的沟通方式将通过系统设计来表达。该法则侧重于组织结构和沟通对系统设计的影响。组织沟通和系统设计密切相关,尤其是对于复杂系统。只有解决了人与人之间的沟通,才能有更好的系统设计。沟通问题会导致系统设计出现问题,进而影响整个系统的开发效率和最终的产品效果。这也是互联网公司追求小团队的原因之一。第二定律:无论你有多少时间,不可能把一件事做得完美,但总有时间去完成一件事。人手永远不够,事情永远做不完,却可以一件一件地完成。这不就是软件行业的“敏捷开发”模式解决的问题吗?面对这样的情况,敏捷开发可以做到持续迭代、持续交付、快速验证反馈、持续改进。开发再好也会写BUG,测试覆盖再全面也无法检测出所有问题。解决的办法不是消除这些问题,而是容忍一些问题的存在,然后通过适当的设计(冗余、监控、高可用设计),在问题出现时能够快速解决。一家只有几个开发人员的小公司正在追求微服务和中端架构。这就是追求完美吗?不行,这是找死。好的架构不是买来的,也不是设计出来的,而是基于业务实现的长期演进。第三定律:线性系统与线性组织结构之间存在潜在的异质同态特征。该定律是第一定律的具体应用。想象一下,如果公司的结构是这样的:团队是分布式的,每个团队包括产品、研发、测试、运维等角色。此时系统为单体应用,项目沟通协调成本巨大,如果做得不好,就会发生争吵。如果将单体系统拆分成微服务,每个团队各司其职,只需要对外提供相应的接口,互不干扰,系统效率会提高,符合高内聚低耦合在软件设计中是相互关联的。说白了,你想建什么样的团队,就有什么样的团队,需要什么样的系统就可以了。团队可以设计一个前后端分离的系统。第四定律:较大的系统总是比较小的系统更容易解体。“论天下大势,久分必合,久合必分。”系统越复杂,需要的人力就越多。人力越多,通讯成本也成倍增加。分而治之是大多数公司选择的解决方案。它分为不同的级别。针对不同的小团队,让团队内部完成自治,然后对外统一沟通。我们尝试从康威定律推导出系统架构的演进方向,我们自然知道微服务的拆解粒度。无论是SOA还是微服务,要解决的根本问题是团队分工的问题,这是大型软件开发的必然,不会因为人的喜好而改变。当你理解康威定律时,你会发现“服务拆分粒度难以准确把握”根本就不是本质问题。如果你有几个2pizza团队,最好将它们拆分成几个微服务。当只有一个开发人员时,尝试制作一个单体应用程序。不要找刺激把它拆分成10个微服务。最终,开发者会将他合成为一。微服务需要一个垂直的2pizza团队(无数的小团队,包括开发、测试和运维)。如果团队还是横向结构场景(开发、运维、测试各是一个团队),比如一些传统的大企业,微服务落地会非常痛苦,尤其是运维团队。总结具体的实践建议:一定要用一切手段提高沟通效率,比如slack,github,wiki。如果两个人都能把事情说清楚,就不要招更多的人。每个人、每个系统都有明确的分工。如果出现问题,您将知道立即联系谁以避免踢球。通过MVP设计系统,通过不断的迭代验证和优化,系统应该是弹性设计的。你要什么样的系统设计,你要打造什么样的团队,能扁平化就扁平化。最好按照业务来划分团队,这样团队才能自然而然地具有自主性和凝聚力。清晰的业务边界将降低与外界沟通的成本。每个小团队负责自己模块的整个生命周期,没有明确的界限。没有无用的争论,互操作,而不是集成。做一个小而美的团队,人多会带来沟通成本,降低效率。亚马逊的贝佐斯有一个有趣的比喻,如果两个披萨不够一个团队,那么这个团队就太大了。事实上,一个互联网公司的小产品团队一般有7、8个人左右。总之,只要思路清晰,运维能力跟得上,服务拆分大体上是合理的!