写点什么

关于微服务拆分,听听一位微服务架构师的肺腑之言

2020 年 12 月 27 日

关于微服务拆分,听听一位微服务架构师的肺腑之言

微服务架构的盛行,解决了系统上可用性、可扩展、可维护性上的问题,成为众多企业架构转型的不二之选。但在架构转型时,原有系统应该如何进行微服务拆分呢?要避免哪些陷阱呢?


引言


天下大势,分久必合,合久必分,架构设计风格随着系统的不断演进逐步进行着分分合合的变化。在整个变化过程中,技术框架的快速发展、用户需求的不断升级、云计算多年来长足的发展等环境因素也对应用系统架构风格产生了重要影响。


IT 市场及从业人员对于技术框架、架构风格不断进行选择和优化。多年来,为了满足用户爆炸式增长的个性化需求,系统架构逐步从单体架构转变为面向服务的 SOA 架构。SOA 架构将单体架构中应用的不同功能模块进行了粗粒度的拆分,各服务间以相同的契约进行通讯,使得系统具备一定的服务化、异构化、松耦合特性。


但在系统变得逐步庞大和复杂之后,服务总线却成为服务通讯的瓶颈。微服务架构将服务粒度更加细化,基于 DDD 让每个微服务达到服务自治,服务间通过轻量级的通讯机制直接调用,每个微服务都围绕着一个具体的业务单元进行构建,使系统各服务间有机解耦,同时又保持互相协作、各自“生长”的状态。


不过微服务的落地需要研发团队满足更高的要求,比如可视化服务治理平台、健全的 Devops 流程等。未来,微服务也可能被取代,例如目前各大云厂商在云原生领域的发展越来越迅速,Google、IBM、AWS 等各大厂商纷纷加大竞争力度,云原生未来必将成为兵家必争之地。



微服务实践经验


目前微服务应用在企业中逐步广泛落地,各大云厂商在各行业中为了推进企业数字化改造落地,都做出了巨大努力和贡献。Iaas、Paas、Saas 平台伴随着云计算产业的快速发展,已经进入了快车道。随着越来越多的企业在微服务架构方面的落地实践,对于微服务架构的可应用场景也越来越清晰。那么,在企业实践微服务架构时需要注意哪些陷阱,才能够让微服务架构在适当的场景中发挥出相应的优势呢?


1. 微服务基础设施不完备


微服务架构的实际落地并没有想象中的简单,在基础设施能力缺失或并不完善之时,就开始微服务的大踏步落地实践,无疑会让团队成员产生诸多困惑。其实,微服务架构在基础设施建设方面需达到比较高的要求,包括平台框架方面的虚拟化技术平台、CI\CD 管理平台、微服务治理平台、监控平台、大数据平台等,研发团队方面的技术水平、运维能力等等。


举个例子,研发团队虽然完成了业务代码的拆分,但由于服务间依赖导致发布时仍存在先后关系,加之基础环境没有容器化等合适的虚拟化技术支持,CI\CD 在效率和可视化方面也不够完善,就很可能会出现生产环境的一次版本发布时间长达若干小时。研发及运维人员的精力被消耗在“盯发布”上,同时系统迭代的效率也大打折扣。


虚拟化能力方面,需要如 Kubernetes、云平台之类的平台技术,帮助应用提升标准化部署、测试快速反馈、可移植性保障、版本化发布等方面的效率。


持续集成方面,需要与虚拟化技术整合,在功能开发过程中可以极大的减少非开发工作所带来的时间成本。


微服务治理方面,试想如果系统服务成千上万,但没有微服务治理平台做支撑,那么服务健康状态要如何掌控?更别提服务路由、限流、降级、熔断等服务治理的成本。


监控报警方面,针对物理机、虚机容器的资源使用监控、服务调用量异常、服务响应异常、整体调用链路状况等,需要统一整合 APM、日志平台、微服务治理平台等一众平台的能力,否则在应用排错、异常巡检、发现隐藏问题、全链路压测等方面都会面临巨大困难。同时提高监控报警平台的可视化能力,也能够有效增加系统运维的整体效率。所以,在开始落地微服务架构以及之后的落地过程中,需要不断补全、完善微服务架构所需的基础设施能力,否则只会“欲速则不达”。


2. 服务拆分方案想当然


在微服务拆分设计方案中,最常见的陷阱就是想仅仅通过将系统进行表面的拆分,就解决原有架构体系产生的诸多问题。比如,将原有单体中模块之间的进程内(内存)调用,简单的替换成微服务架构下的进程间调用(网络)。这种为了拆分而拆分的做法不仅增加了代码拆分、微服务部署、功能测试等方面的成本,还会增加“网络”这一不可靠因素(相比网络内存显然更加可靠)。


举个例子,两个功能模块在拆分前都由小明同学维护,功能在拆分成 8 个微服务之后还是由小明同学维护,但他需要将原有代码逻辑进行分拆,同时增加微服务通讯的代码,还要保证分拆后代码的质量。负责测试的小红同学还要重新跑通全流程测试,负责运维的小刚同学还要针对微服务架构重新进行硬件、网络改造等……如果仅仅是简单的“拆开”,而没有在拆分过程中考虑加入 MQ、定时任务、大数据异步处理等手段来解决单体应用高耦合的问题,最后只能让系统变成“分布式单体”。


在进行微服务拆分时应当更多的考虑“高内聚、低耦合”原则,对现有业务梳理出核心、非核心链路,在合适的业务场景利用同步、异步的调用方式进行适当的编排。


另外,微服务拆分是企业系统架构的一个演化过程。出于稳定性、业务发展的考虑,目前哪一部分可以优先拆分,哪一部分目前不适合变动,都需要架构师认真考量。尤其是在数据层面上的拆分,提前做好冷热数据分离、数据归档等操作,为数据拆分降低难度。


同时在微服务拆分后,如非必要情况要防止同一份数据在多个微服务中以不同的格式存储,这样持续发展数据会变得越来越难以维护,并且在复用层面上也会比较混乱。最后,微服务架构拆分需警惕“表面功夫”,根据自身业务场景和当前能力因地制宜的进行前、中、后台规划设计,才能保证微服务架构落地成功,并根据自身特点逐步演化。


3. 忽略人和业务的复杂性


当微服务架构逐步落地企业的过程中,很难保证组织内相应的变更及时跟进,即都想要遵守康威定律,但实际落地可能困难重重。架构调整所带来的工作内容变动与团队各研发角色对原职能的固守之间的矛盾会在暗地里涌动。归根结底,人的问题才是最难解决的问题。


举个例子,微服务改造前开发人员小明和运维人员之间交集并不多,但实施微服务需要做 Docker 容器化,那么 DockerFile 中需要引用的组件、配置参数要由谁来定义?做的越多,错的越多,所以很可能小明和小刚都不愿意做。退一步讲,如果由小明定义,那么小明 2、小明 3 陆续编写自己的 DockerFile 后,小刚就会崩溃于容器化配置非标的问题。如果由小刚同学编写,那么众多小明同学的个性化配置得不到满足,小明们未必会继续支持微服务改造。所以,微服务架构改造需要添加“人”这一因素,重新确定角色的责任边界、服务边界,统一开发能力让业务开发能够快速进行


再比如,面对比较复杂的业务时,整个调用链路会很长,当调用接口变化(如需要在链路入口增加一个参数并一直传递到链路末端)时,就需要协调每个微服务的小明们进行代码修改,还需要协调每个微服务的小红们进行测试,还需要每个微服务的小刚们进行发布生产。发布虽然成功了,但是大家都在隐隐的扪心自问:我们不是已经做了微服务改造,不过为什么感觉上没什么改变?可以看到,大家并没有理解的是,微服务改造后业务本身的复杂性只是被转移到了每个服务上,而其本身并未消失。架构师作为微服务架构的规划者,应统一开发能力让业务开发能够快速进行,减少业务开发过程中的复杂性,如让团队有统一的中间件平台、统一的工具组件,以较少的开发成本完成既定的业务功能。


4.微服务并不完美


微服务架构并不是银弹,如果把它当做摆脱现有困境的救命稻草,反而会适得其反。微服务是个好东西,但是无论是从单体直接切换到微服务,还是从 SOA 过渡到微服务,都应根据自身技术能力、业务规划、组织情况、预期规模等方面考虑,找到让整个团队在一个阶段内都相对“舒适”的平衡点,不要因为跟风“微服务””云原生“而过于激进,也不要在架构变更上一味求稳而过于保守。企图使用一种单一的架构模式适应所有的使用场景,这种想法本身就很危险。


项目实践


项目一


1.项目概况


业务主要是通过微信小程序接入用户信息并进行采集记录,功能模块主要包括用户管理、权限认证、进度跟踪、报表导入导出、任务调度(Pyhton)、数据抽样、数据统计等。


2.拆分步骤


模块划分:


  • 基础管理:包括用户管理、权限认证、进度跟踪。功能相对简单且业务耦合性较强,业务相关接口流量比较平均,所以整合为一个服务。

  • 导入导出:包括报表的导入导出。大数据量的导入导出操作对内存 、CPU 的消耗较大,为防止导入导出时影响其他业务,所以单独拆出。

  • 任务调度:包括各任务的调度。由于任务调度使用了异构的 Python 框架 celery,并且任务调度属于支撑平台部分与业务不相关,所以单独拆出.

  • 数据管理:包括数据抽样、数据统计。对已有数据进行统计分析属于离线操作,其特点是数据量普遍较大,实时性要求不高,跟实时数据操作不同,所以单独拆出。


3.拆分建议


避免单个微服务内各业务场景间的资源(CPU、内存)争抢。比如,导入导出的各个场景之间是否存在资源争抢、Python 任务同一执行时间段内的资源争抢。


  • 使用异步方式对微服务调用链条上耗时比较长的进行解耦。

  • 通过相对准确的数据指标(调用量、资源消耗)进行微服务拆分粒度的决策,避免拆了又合或拆的太粗。


项目二


1. 项目概况


业务主要支撑百余家经销商完成线上培训,功能主要包括经销商主数据、招募、选建、项目管理、权限管理、信息发布等,涉及服务近 50 余个。


2.拆分问题


  • 数据并未跟随服务一起进行拆分。根据具体业务逻辑分析发现,有一部分服务的数据并不相关,但是却耦合在了一个数据库中。未来如果上述其中一个服务对应的数据爆发增长,那么将给整个库的读写带来压力,间接影响了库中的其它服务。

  • 单个服务对其它服务的依赖过多。根据调用链路分析发现,个别服务对其它服务的依赖关系过多,但由于历史原因导致核心代码不敢做大的改动,此处风险在于关联过强的服务变动频繁就会对被关联服务产生影响。

  • 部分服务拆分粒度过细。经过分析服务的业务逻辑,发现个别强耦合服务被分拆。

  • 持续集成基础设施能力不足。目前还停留在 jenkins 手动触发拉取代码、编译、打包的阶段,每次发布耗时近 20 分钟。

  • 组织成员协作效率低下。项目涉及开发、基础设施、架构、管理等多个参与方,但是没有一个有力的组织协调者进行统筹,导致各自为政。


3.拆分建议


  • 根据业务重新梳理微服务划分粒度,强耦合少关联的业务就合并成一个服务。

  • 同时对数据库进行拆分,将非强耦合的数据拆分到多个微服务中去,可以存在若干服务调用一个数据库。

  • 设置一个项目的统一协调部门,协调开发、运维对持续集成流程、容器化环境进行优化。尽量达到测试环境本地代码变动,可以自动触发远程编译打包发布的动作,总过程时间尽量控制在 5 分钟之内。

  • 由统一协调部门初步划分各研发角色的主要责任,避免出现责任边界不清晰导致的推诿。


总结


笔者个人认为,系统进行微服务改造之前要先充分了解自身情况,根据自身情况先扪心自问是否需要进行微服务拆分。然后,微服务拆分是一步步循序渐进的过程,其成功与否取决于对架构演进的把控能力以及实施细节上的逐步完善和调整。最后,积极的从组织内外听取经验意见,经验意见不一定对,但是可以触发架构师的思考,可以有效避免微服务拆分中的“深坑”。


【参考文献链接】




头图:Unsplash

作者:崔凯

原文关于微服务拆分,听听一位微服务架构师的肺腑之言

来源:腾讯云中间件 - 微信公众号 [ID:gh_6ea1bc2dd5fd]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2020 年 12 月 27 日 22:271444

评论

发布
暂无评论
发现更多内容

如何让解决无法访问 GitHub 的问题?

JackTian

GitHub

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(四)

图雀社区

Vue Node

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(六)

图雀社区

node.js Vue

为什么你成不了「超级个体」?

非著名程序员

程序员 互联网 提升认知 认知提升

csapp-chapter2

卓丁

深入理解计算机系统 csapp

Sula - 可能是西湖区最好用的antd配置框架

开远

前端开发 antd sula 配置化开发 前端框架

自定义 SpringBootStarter

lee

重磅推出:第14份年度敏捷状态报告(最新2020)

Bob Jiang

敏捷 调查报告 state of agile

大话设计模式 | 0 面向对象基础

Puran

C# 设计模式

ArrayList浅析

章小传

Java collection 原理 ArrayList

分布式事务 - 三种常见的解决方案

Java收录阁

分布式事务

愚蠢写作术(2):怎么让你的文章变得冷冰冰

史方远

学习 个人成长 写作

源码分析 | 像盗墓一样分析Spring是怎么初始化xml并注册bean的

小傅哥

源码分析 小傅哥 spring源码 bean注入过程

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(三)

图雀社区

vue.js Vue Node

csapp-chapter1

卓丁

深入理解计算机系统 csapp

JDK 15 都发布了,可 Java 8 依然是最爱

古时的风筝

Java Java 25 周年 Java版本

N皇后问题之位运算解法

孙苏勇

算法 DFS 位运算

React之Context源码分析与实践

费马

源码分析 React useContext Context React-Router

做一个纸上谈兵的项目经理

escray

我的个人知识管理方法

lidaobing

个人成长 知识管理 PKM

除了公关,我还能为公司做点什么?(系列1)

邓瑞恒Ryan

学习 个人成长 自我管理 成长 职业成长

SpringCloud-OpenFeign源码

云淡风轻

Spring Cloud

【译文】为什么说Rust是机器人技术的未来

袁承兴

rust 机器人 嵌入式

架构师必备的ToB产品交付之双轮驱动思维模型

常平

产品 极客大学架构师训练营

从零到部署:用 Vue 和 Express 实现迷你全栈电商应用(五)

图雀社区

Vue Node

JUC整理笔记五之梳理Varhandle(下)

JFound

Java

路径依赖 - 偶然决策导致的依赖。

石云升

思维模型 路径依赖 网络效应 沉没成本 价值网依赖

中台上线半年,我总结出了“七宗罪”

夜来妖

中台 企业中台 后台开发 业务中台 后台

多来点胜利,对冲颓丧

zhoo299

成长 备忘

科学提升认知方法之贝叶斯公式

奈学教育

贝叶斯公式

GitHub上10个不可错过的另类有趣项目

码农神说

GitHub 程序员人生 开源项目

关于微服务拆分,听听一位微服务架构师的肺腑之言-InfoQ