hth华体会体育全站app_记一次事情中微服务项目迁移拆分的历程

时间:2023-02-07 15:24 作者:hth华体会体育全站app
本文摘要:前序额,十分遗憾,这次并不是分享BUG了,所以不能让大家看到我出糗的样子了,而且,这次也没有太多技术性的内容,几多会显得有些枯燥乏味。不外呢,可能本次所涉及到的项目迁移拆分方案,在诸位看来也并非完美,所以列位还是有时机品评一波,娱乐一波。 配景话不多说,我们先来谈谈这次这次项目迁移拆分的配景。

hth华体会体育全站app

前序额,十分遗憾,这次并不是分享BUG了,所以不能让大家看到我出糗的样子了,而且,这次也没有太多技术性的内容,几多会显得有些枯燥乏味。不外呢,可能本次所涉及到的项目迁移拆分方案,在诸位看来也并非完美,所以列位还是有时机品评一波,娱乐一波。

配景话不多说,我们先来谈谈这次这次项目迁移拆分的配景。经典模型我们先来看看现在大多数微服务框架的系统架构,这里以Dubbo为RPC服务基础,而且用传统的电商业务模型(熟知我的观众肯定知道,我向来是掩护公司业务代码的,所以这里使用大家广泛熟知的业务模型为例)。简朴解说下:这是一件简朴的电商业务模型,在微服务业务细分下,分为用户服务、商品服务、生意业务服务、仓储服务、售后物流服务、财政服务。

(要是详细细分以及其他服务的就不在这里多说)微服务架构接纳Dubbo作为服务治理框架,各个服务通过Dubbo举行RPC通信。各个服务当中涉及到的实体类、工具类、Dubbo接口等放在公共接口服务当中(我也不知道该怎么说,其实就是一个公共的jar包,不能说是一个服务,但现在临时这么称谓吧),由各自业务服务web工程举行引用,其实就是在maven的pom文件当中引用。以上可能是最简朴的一个模型,固然在业务、架构上各个公司都有自己的方案以及扩展之类的,这就不再思量之内,可是其实焦点还是围绕着这个最原始的模型。

当前现状那么现在遇到了什么问题?我们再来看看这样一个模型。各自的业务服务web工程都市对这个公共服务举行依赖,这自己也没什么问题,究竟这内里放的都是一些Dubbo接口等,详细的实现类还是在各自的服务工程当中。

可是问题来了,不知道从什么时候开始,这个模型发生了变化,就是所有的实现类都写在了这个公共接口服务内里。由于这自己就是多模块的maven工程,于是各自的web工程引用自己所需要的那一部门module。于是所有的web工程只是一些差别情况profile下的设置文件。这个就与上面的模型的初衷南辕北辙。

如图所示:​发生影响那么这样会有什么问题:项目结构的问题。所有人的代码都在这个公共接口服务当中,使得结构变得很杂乱,对于web工程甚至会引用不属于自己的module,例如商品服务当中引用了财政的实现类,本质上走的是dubbo协议,web工程反而引入了一些多余的jar,甚至还会引起maven的依赖优先的问题,造成事故的风险点。

(maven的依赖优先指的是引用差别module可是包罗了同一个jar的差别版本的情况,maven接纳依赖最短路径优先原则,这个有时机再之后的文章中细说)代码治理的问题。由于差别模块的代码都在这个公共服务当中,在合并代码的时候会发生大量冲突。例如商品服务的同学提交接码举行Merge的时候会发生发生大量的冲突,这些冲突基本上是非自己业务模块,或生意业务、或仓储、或其他业务模块等。

在理想模型下,也就是在我第一个图片当中,那么举行merge发生的冲突也应该是各自业务模块的代码冲突,这个是免不了。(导致合并代码最后演化成copy code的模式,或者使用Git提供的cherry-pick,可是本质上其实也是高级版的copy code,而无法使用正常的merge)部署治理的问题。既然大家都把代码合并在这个公共服务当中,那么在CI部署的时候(不管是gitlab上还是Jenkins),编译打包这个历程就十分缓慢。

原本这些编译打包的肩负可以落在各自业务web服务中,现在反而都集中在这一个服务当中。随着日后业务代码的不停增多,这个时耗将会变得越来越长,甚至一旦有代码堕落导致整个部署公布都失败。这个是现在视察下来最为头疼的几个痛点。

这个事情我从去年一直不停反馈,这个公共服务需要举行拆分。可是一是由于一些部门层面上的原因,二是业务生长吃紧,也没有人也没有这个时间去主导或者去推动跟进这个事情,导致这个事情一拖再拖,于是就陷入了一种恶性循环的田地。直到这次双十一,因为大促期间无法公布,所以也就没有需求迭代。

于是我再次提出这个事情,这次总算是有时间去推进这个事情。(我还是认为,既然已经发现诸多的痛点,还是应该想着提前去根治,否则这早晚是一把达摩克利斯之剑,要么在一开始就应该防止这种事情的发生)​实施前那么现在想想,应该怎么去入手这个事情。

(是不是以为这个事情看上去似乎没啥技术含量,可是突然就不知道怎么做,我其时还以为是大佬们去做这个事情,可是大佬们有其他优化,所以就酿成谁提出,谁解决。固然,做法式员嘛,还是以解决问题为主)分析目的我们的目的是将业务详细的实现类(这里主要是service层的实现和controller层的接口)迁移至各自的web工程。

那么,首先想到的是是否可以直接从公共服务当中删去那些代码,然后新增到各自的web工程呢,或者通过git操作举行合并。那么我以为,如果只是从做法上考量,两种谜底固然都是可以。可是呢,要是这么简朴的话,我今天也就没有须要写这篇文章了。我们想想,要是真的就这么做了,会有哪些问题:第一种,如果是删除代码,移动代码的话,这种做法我以为是效果最差的。

因为虽然你代码是实现了转移,可是一并的也失去了git上面的commit记载,其次还无法保留项目当中的各个分支。第二种,似乎效果是好了一点,可是由于工程结构的纷歧样,在通过Git操作之后会有大量的冲突。网上也有许多的类似操作,可是由于网上提供的demo业务场景比力单一过于简朴,就像这种git如何合并两个项目?,而且实际上的操作也比这种demo庞大且难实施,风险点过大不行控。项目分支可能许多人会奇怪,既然我是迁移项目,为什么还要保留分支。

首先,我们要明确,如果是那种几个月前的开发分支,或者只是为了合并代码生成的合并分支,这种分支对于整个工程来说,意义不大。在迁移的时候重要的分支其实就是分为两类:现阶段正在开发的开发分支,例如feature/abc;具有重要里程碑意义的分值,例如灰度情况: gray/abc,或者是特殊分支: vip/abc,亦或者是预发分支: release/abc,另有就是这种备份分支: remaster/abc等等。

hth华体会体育全站app

为此这类分支就要毫无保留的举行迁移,保留对代码工程的维护性。固然我们公司还存在着另外一个特殊性,给这件事情造成极大的难题。由于我们公司是一家To B企业,所从事的业务也是面向企业的,所以对差别类型的公司就会进入到差别的情况,我们称之为“灰度情况”(虽然小我私家认为称为这里灰度与实际意义上的灰度意思有点不符,我所认为的灰度可能更多还是倾向于小流量用户所处情况,且用于新功效测试阶段的灰渡过渡,这个可能就是To B与To C的差别吧)。

于是在我们公司就会存在许多“灰度情况”,这个给推进这个项目迁移事情带来极大的阻力。我之所以在这里先容这么多篇幅,是因为这个确实是造成了很大问题:首先,既然是项目迁移拆分,那么肯定不是一个晚上全部改掉完成,想想有这么多情况的存在;而且就算通宵革新,那么就不怕泛起风险嘛!这个锅背不起。其次,如果革新的话,那么公共接口服务当中详细的实现类肯定都是要删掉的(git上删除),剩下一个光秃秃的公共接口,那么列位开发同学在开发的时候,肯定会从这个光秃秃的公共接口服务的master切出分支。

正常情况下是一个情况一个情况的举行更迭,那么当有紧迫bug需要修复的时候,从这个光秃秃的服务中切出的hotfix分支合并到还未革新的情况的时候,就会把对应情况的你谁人服务上的代码都删除了,可是谁人情况由于还没有举行革新,而此时又发生删除情况,那么这显然就会失事。除非在某一时刻全部革新完成来制止这种情况,例如上面1中所说。

如图所示:​实施方案那么岂非就真的无济于事了吗?厥后我仔细思量了下,既然一步到位的事情做不到,那么是不是就可以绕一下曲线救国。于是我寻思着,既然不能直接革新,那我是不是每一个业务服务可以重新镜像出一个公共接口服务,将依赖从原先的公共接口服务转移到这个公共接口服务镜像当中,由于各自业务都有自己的镜像,那么只需要对各自的镜像举行修改,这样改动与影响就小许多了。

如图所示:​ 这样做有如下利益:既然是复制镜像的做法,你那么整个Git工程当中的commit记载和所有的分支都保留。每一个业务模块都可以对自己的镜像举行增删改,而不会影响到其他业务模块。

每个情况迭代公布,只需要将maven引用转移到公共接口服务镜像即可。我们来看看接下去的情况迭代:​ 这样就可以制止上面的问题,对于未迁移的情况和已经迁移的情况,都可以很好的兼容。最后的问题可是这里另有一个问题,不知道列位观众有没有注意到,那么原先的公共接口服务,该怎么处置惩罚呢。这里也碰面临是否删除代码的问题:如果删除代码,可是这样又跟适才说的第2点的问题是一样了;如果不删除代码,那么原先的公共接口服务当中和镜像当中的实现类就会重复,这样两者举行编译的时候,后一个编译打包的就会笼罩前者,也会存在问题。

那么怎么办呢?这个还是主管给我提供了思路,由于原先公共接口服务的maven坐标和镜像的maven坐标是一样的,那么就需要将镜像的maven坐标举行更名,然后让web工程引用镜像的maven坐标,这样,即便同一个实现类在公共接口服务和镜像中都存在,可是web工程实际上加载的只会是镜像当中的class,这样就能解决这种问题。实施中既然上面已经将思路与方案都已经论述清楚,那么接下来举行实施,这个历程就相对容易点了,就似乎高楼大厦,架子已经搭建好了,只需要搬砖即可。

由于各个业务都是由各个业务小组举行推进,业务迁移拆分也有先后顺序,那么就以商品服务的拆分为例来展开:通知各个开发,主要是商品服务开发人员,在统一时刻举行分支提交,因为需要将公共接口服务举行镜像复制。这是很关键一点,否则当复制出镜像之后,尚有分支还在原先公共接口服务当中,那么这个分支上的功效代码的迁移就会十分鸡肋。在镜像当中只保留商品服务的实现类,包罗controller、service实现类、business,dao等,其余非商品服务代码都举行删除,commit而且push。修改maven坐标,举行更名,这里的更名最快的方法就是修改groupId,例如原先叫com.abc.abc,那么现在修改为com.abc.xyz,而artifactId稳定,依旧保持语义,例如abc-item。

version:set。这个就是在对应情况中举行部署打包,正式情况肯定是deploy。在商品服务的web工程中,将涉及到依赖商品实现类的maven坐标举行修改,其实就是修改groupId就好,这样web工程就引用到镜像而不是原先旧的公共接口服务。

公布,检查启动是否报错。固然,我是在镜像当中加了一个心跳请求controller,来验证请求是否走到了镜像当中的代码。那么对于其他开发同学的情况,我们这边也需要举行思量一下:非商品业务开发: 原则上,这些开发的改动是不能够触及商品业务的代码。

可是由于之前都是在一个公共接口服务当中,这一点就很难保证。这种情况的话,要么予以驳回,要么就是配合copy code将这些代码复制到举行当中;商品业务开发: 在切出镜像之前,有些同学已经有了业务开发的分支,那么这种情况下,只需要将镜像的master分支举行反向merge即可,因为master分支是只保留了商品的业务代码,其他代码都已经举行了delete,在反向merge之后,也一并会将那些代码举行删除;而在镜像已经切出来之后,那么如果需要开发新功效或者举行hotfix的话,那么只需从镜像checkout出新的分支即可。实施后在迁移拆分之后,需要举行简朴验证。

这里我以商品服务为例,在镜像当中的Controller层写一个心跳请求:@RequestMapping(value = "/healthCheck", method = RequestMethod.GET)@ResponseBodypublic Object healthCheck() { return successResponse();}那么如果可以请求到这个接口,说明商品web服务工程已经乐成引用了镜像内里的module,其余业务模块也都可以用这个方法监测。小结总的来说,可能本次项目迁移拆分的工程,难度更多的还是偏向治理方面的考量。虽然我不太清楚现在其他公司的项目架构是否有遇到这样的瓶颈,但就我身边朋侪所处小公司的项目,也几多可以窥见接下来的趋势也会遇到相同的问题。

其实也不难明白,在前期还是以生长业务为主(肯定是赚钱要紧,否则谁来发人为),只是我以为,任何前期小型项目演化成一个巨无霸的时候,一定要意识到项目对于现在团队建设所影响到的方方面面,因为细节决议成败不只是书上说说的原理。另一方面,在我们不能一蹴而就的情况下,需要举行一定水平上的曲线救国,通过引入中间环节来解决问题。正如上面所述的解决方案中,通过引入镜像以及更改maven坐标的方式,来间接实现迁移拆分的效果,而且在这种多情况的场景中也能很好的实现兼容,而且在业务中将代码实现了隔离,大大增强了系统的可维护性。作者|showyool|掘金。


本文关键词:hth,华,体会,体育,全站,app,记,一次,事情,中微,hth华体会体育全站app

本文来源:hth华体会体育全站app-www.ytjiaxinyasuoji.com