导语:微服务架构的盛行,解决了系统上可用性、可扩展、可维护性上的问题,成为众多企业架构转型的不二之选。但在架构转型时,原有系统应该如何进行微服务拆分呢?要避免哪些陷阱呢?在本文中,腾讯云微服务架构师崔凯将为大家详细解答。
天下大势,分久必合,合久必分,架构设计风格随着系统的不断演进逐步进行着分分合合的变化。在整个变化过程中,技术框架的快速发展、用户需求的不断升级、云计算多年来长足的发展等环境因素也对应用系统架构风格产生了重要影响。
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分钟之内。
由统一协调部门初步划分各研发角色的主要责任,避免出现责任边界不清晰导致的推诿。
笔者个人认为,系统进行微服务改造之前要先充分了解自身情况,根据自身情况先扪心自问是否需要进行微服务拆分。然后,微服务拆分是一步步循序渐进的过程,其成功与否取决于对架构演进的把控能力以及实施细节上的逐步完善和调整。最后,积极的从组织内外听取经验意见,经验意见不一定对,但是可以触发架构师的思考,可以有效避免微服务拆分中的“深坑”。
【参考文献链接】
https://www.infoq.cn/article/Nd0RofAUp0WtlvlQArbu
https://www.infoq.cn/article/KSzctluch2ijbRbKYBgO
https://blog.51cto.com/ygqygq2/2332823
《聊一聊微服务架构中的服务发现系统》
《探寻繁杂定时任务的解决方案:分布式任务调度系统》
《腾讯云中间件团队在Service Mesh中的实践与探索》
《Kafka集群突破百万partition 的技术探索》
《服务治理最佳实践:如何快速依据请求参数值进行服务路由、鉴权、限流?》
了解更多微服务、消息队列的相关信息!