阿里一面:微服务拆分需要考虑什么因素?

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

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

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

对于单体应用,通讯在进程内部进行,下单方法调用扣库存方法,有问题就回滚事务,利用数据库同一个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人左右。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85301.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3D高斯泼溅和4D高斯

1.高斯函数 想象你往平静的湖水里扔一块石头,水波会以石头落点为中心向外扩散,形成一个逐渐衰减的圆形波纹。高斯函数的形状就和这个波纹类似: 中心最高(石头落点,波峰最强)。越往外,高度&…

comfyui插件和comfyui mac安装

mac comfyui安装包 ComfyUI.zip,官方最新0.3.40,如果后续官方有迭代,可以直接通过git更新源码升级 comfyui插件下载,解压放到custom_nodes目录下,包含 comfyui-animatediff-evolved(视频插件) 和…

面试题SpringCloud

SpringCloud有哪些特征? 分布式/版本化配置服务注册与发现路由服务到服务的调用负载均衡断路器领导选举和集群状态分布式消息传递 SpringCloud核心组件? Eureka 注册中心Ribbon 客户端负载均衡Hystrix: 服务容错处理Feign:声明式Rest客户端Zu…

ASR-PRO语音识别可能出现的问题

ASR-PRO语音识别可能出现的问题 4月份有一天刷到牢大/爱丽丝语音自开关灯设备,心血来潮,博主也是浅尝了一下,由此也总结一下,实现此项目会出现的问题。 在实现爱丽丝开关灯模块时ASRPRO语音识别可能出现的问题如下: …

苍穹外卖--缓存菜品Spring Cache

Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring Cache提供了一层抽象,底层可以切换不同的缓存实现,例如: ①EHCache ②Caffeine ③Redis 常用注解…

个人简历制作MarkDown模板

MarkDown制作个人简历的模板放在了github上,大家如有需求,请自取: https://github.com/QQQQQQBY/ResumeTemplate 介绍一下此模板的特点: 🌸个人面试期间使用的、整理的简历格式,现在分享给大家。 ⭐简历采…

【MySQL数据库 | 第五篇】DDL操作2

文章目录 当前数据库student的数据数据表操作 - 修改&删除📖修改操作增加字段👏案例:向数据表student中添加字段 id修改字段的数据类型【只能修改字段的属性】👏案例:将student表中字段age的属性由tinyint unsigne…

【浏览器插件】如何开发一个Chrome浏览器插件

这篇文章来介绍一下,如何开发一个自己的Chrome浏览器插件程序。 Chrome浏览器插件,其实是让浏览器替我们执行我们自己写的代码,既然要让浏览器执行代码,那么首先,就需要定义一个规范,也就是说,需要让Chrome浏览器知道,你写的程序是一个插件。 这就需要介绍一下插件中…

详细讲解Redis为什么被设计成单线程

Redis 被设计成单线程的原因主要有以下几点,这些原因涉及性能优化、复杂性控制、数据一致性以及适用场景等多个方面: 1. 简化设计与实现 避免锁竞争:多线程环境下,多个线程访问共享资源时需要加锁来保证数据一致性。锁的使用会增…

Hive 逻辑优化器

Optimizer PointLookupOptimizer 作用:把符合条件的 OR 表达式转为 IN。 参数hive.optimize.point.lookup 设置是否开启 PointLookupOptimizer,默认为 true. 参数 hive.optimize.point.lookup.min 控制多少个 OR 表达式转为 IN,默认 31。 例…

ZYNQ Petalinux实战:PCIe直通NVMe固态硬盘,解锁存储性能新极限!

突破SD卡和SATA的速度枷锁!本文将手把手教你如何在ZYNQ平台上通过PCIe接口驱动NVMe固态硬盘。从硬件设计、Linux内核配置到创新性的DMA零拷贝优化,实现2000MB/s+ 的存储性能飞跃,附完整代码解析和性能实测对比。 一、为什么选择PCIe NVMe?存储性能革命 ZYNQ传统存储方案面…

05-mcp-server案例分享-用豆包大模型 1.6 手搓文生图视频 MCP-server发布到PyPI官网

1前言 上期给大家介绍过mcp-server案例分享-用豆包大模型 1.6 手搓文生图视频 MCP-server。当时部署的方式使用了一个私有云SSE的部署。当时缺少一个本地部署的方式,有的小伙伴给我留言能不能有一个本地话部署方式了。今天就给大家带来一个本地化部署的方案。 话不…

MCP Parameters 增加描述

场景:本地MCP开发完后是否发现CLINE上显示的Parameters 显示No description 方法1 :使用参数元数据 (Annotated) 可以使用 Pydantic 的with 类提供有关参数的其他元数据Annotated。这种方法更受欢迎,因为它更现代,并且将类型提示…

STM32 GPIO 寄存器开发

🔧 ​一、核心寄存器概览​ ​寄存器​​功能​​位宽​​关键位域​​GPIOx_CRL/CRH​配置引脚模式(输入/输出/复用/模拟)和输出参数32位每4位控制1个引脚:CNF[1:0](模式) MODE[1:0](速度&am…

powershell 获取 用户及进程列表

在PowerShell中获取用户的进程列表,可以通过几种方法实现。以下是一些常见的方法: 方法1:使用Get-WmiObject Get-WmiObject命令可以用来查询Windows Management Instrumentation (WMI)数据库,从而获取关于进程和用户的信息。 # …

量化面试绿皮书:15. 假币一

文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。 15. 假币一 有 10个袋子,每个袋子里有 100个相同的硬币。 在除一个以外的所有袋子中,每枚硬币重10 克。 然而&#x…

Java求职者面试:Spring AI、MCP、RAG、向量数据库与Embedding模型技术解析

Java求职者面试:Spring AI、MCP、RAG、向量数据库与Embedding模型技术解析 第一轮:基础概念问题 1. 请解释Spring AI是什么?它与传统Spring框架有何不同? Spring AI是Spring生态系统的一部分,专注于人工智能和机器学…

tp框架导出excel的时候报错:unexcepted identifier “Closure“,excepting variable

记录一个简单的错误。 背景 用的是PhpOffice/PhpSpreadsheet 在本地环境下是可以正常导出excel的。但是线上就不行。 就会报错unexcepted identifier “Closure”,好像是不能用匿名函数。 首先 本地可以正常导出,然后服务器上不可以。看了各种日志。ph…

[Java恶补day24] 74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。 …

解锁VSCode:从入门到精通的全攻略

目录 一、VSCode 初相识二、安装与基础设置2.1 下载安装2.2 基础设置三、核心功能深度剖析3.1 强大的代码编辑3.2 高效的版本控制集成3.3 实用的调试工具四、插件扩展,拓展无限可能4.1 插件市场探秘4.2 必备插件推荐五、个性化定制,打造专属开发环境5.1 快捷键设置5.2 用户代…