如何把复杂单体应用快速迁移到微服务

发布于 2018-07-05 | 更新于 2020-09-20

从我接手过的一个项目说起。 先上一个无关紧要的图提提神:

水上木屋

随着项目快速迭代,项目代码变得臃肿,数据表已经接近一百张了。其中部分模块代码消耗cpu和内存大,十几个开发人员在同一个工程里面同时开发着十来个特性,系统如下问题凸显:

1、特性耦合,发版困难 往往一个特性的改动,会牵涉到若干模块,多个特性代码改动重叠,给测试以及合板,发版带来了极大的考虑,降低了发版的效率。 2、非弹性部署,扩展能力差 有些模块需要消耗大量cpu和内存,有些模块需要支持高并发,有些模块需要很少的服务器资源,由于都在单一的系统中,各个模块之间公用同一套服务器资源,分配不均衡,不能针对具体业务进行合理配置扩展。 3、系统业务复杂,接手项目困难 在单一的系统中,涵盖了众多的业务,一个新入职的同事,花三个月可能都未必能熟悉所有的模块,模块间的各种耦合更是让人伤神;不敢轻易调整代码,修改一个问题极易引发另外一个问题。 4、技术升级困难 由于在同一个项目中,技术架构单一,引入一个新技术对所有模块均会有所影响,调整难度极大,增加技术升级风险,整体技术成保守状态,难以升级以适应快速发展的互联网技术。 为此,服务化拆分提上了日程,喵~

猫

服务化拆分流程

摸透系统里面所有的业务和数据库的前提下,我们才可以进行服务化的拆分。由于该系统在线上运营时间较旧,在继续迭代了若干需求和线上问题跟进之后,参与系统迁移的同事对整个系统的业务都了解的前提下展开服务化拆迁工作。 先梳理各个模块的数据模型,然后确定每个模块的职责,从而可以梳理清晰各个服务的边界。

1、解耦老系统外部关联

实际的业务场景和系统交互异常复杂,在这里我简化成以下模型进行说明:

外部系统解耦

根据确定下来的服务的职责和边界,创建新服务程序和数据库,在新服务中约定BC接口,把老系统中对外依赖A全部转接到新系统,新系统通过编写的路由器,把请求路由到老系统。 之所以把外部系统关联解耦放在第一位,是因为外部系统对接需要协调对应的项目组配合整改,周期不可控,需要先把这部分不可能的先完成上线,方便后续系统内部模块快速拆解上线。

2、解耦老系统模块间关联

模块间解耦 老系统模块间直接调用A,提升到rpc或者http调用B,对外暴露接口,打断原有模块间业务层或者数据层的直接调用; 原有系统数据库sql关联查询需要按照模块进行拆解,避免跨模块表关联操作;

3、程序迁移到新系统

程序迁移 按照模块,把相关程序迁移到新系统。 在做解耦老系统模块间关联和程序迁移的时候,需要对老系统业务有深刻的掌握,清晰数据库所有表和字段的作用,以便能快速迁移。 如果我们要求在系统迁移升级的过程中,需要实现不停服,线上业务持续在运行,我们需要实现新老库双写,方便验证没有问题之后,再切换到新的数据库。

4、老系统数据全量迁移

把老系统中的所有数据,通过脚本直接迁移到对应新的数据库中。至此,所有业务数据的写入和读取都是基于新服务的数据库了,从把老系统迁移到了新系统。

关于服务化拆迁的灰度上线

根据系统的业务,制定对应的灰度上线策略。由于我们系统整个业务是围绕着产品来开展业务的。所以可以在灰度发布(金丝雀部署①)的时候,发布灰度测试产品,将白名单用户流量打到新版本的服务器分组上面进行验证。待验证没有问题之后,再逐步开放给全量用户。 在验证期间,旧版本如果需要继续流入业务数据,所产生的新的和改动的业务数据需要再次增量迁移到新数据库中。这样会增加增量数据迁移的工作量,容易出错。我们在升级的过程中停止了老版本系统业务数据入库: 其中灰度测试用户产生的数据只存在于新数据库中。

如何给快速迭代的系统进行拆分

一般互联网企业版本迭代速度都比较快,所以系统迁移的速度一定要迅速。如果周期太长,一个大的需求下来,系统改的面目全非系统迁移的相关工作就得重头再来了; 为了能尽快推荐系统拆分,总结以上流程,我们要考虑如下三个步骤:

  1. 需要外部项目组配合的事情先处理完:创建新服务,进行依赖迁移(迁移外部系统依赖,迁移外部消息依赖);
  2. 接口系统内模块间依赖,定义好服务的职责和边界;
  3. 快速迁移模块到新服务,同时进行数据迁移,进入灰度测试环境;
  4. 灰度测试验证完毕,迁移增量数据到新数据库,全量用户迁移至新系统; 5、线上稳定后,下线老系统,回收相关运维资源。

迁移之后要继续完善的事情:

  1. 跟上服务化技术配套:服务拆分之后,系统的运维需要辅助额外的代价,维护和测试难度几何级别增加,我们必须要对应的配套技术:自动化测试,持续集成,自动化部署,配置中心,任务中心,日志监控等;
  2. 分布式一致性事务问题:为了解决此类问题,我们可以通过业务补偿、可靠事件模型,TCC模式进行开发。

系统迁移工作中带来后续工作的启发

  1. 即使是没有做服务化拆分,系统间各个模块也要职责边界定义清晰,梳理清晰业务模型,保证模块间的低耦合,以及模块的高内聚;
  2. 尽量避免过多的数据表关联查询,把数据库当成存储数据的介质,业务逻辑转移到程序中实现,这也为后续分库分表,服务化拆分做好了准备;
  3. 提前准备服务化配套技术,重视底层平台大家。强大的底层平台支撑,帮助我们填平前人已经踩过的坑:灰度发布,服务升级回退,服务注册发现,熔断降级,自动化部署等;
  4. 服务化之后,新技术尽量从边缘业务进行尝试,积累相关的迁移,服务化,运维问题,构建了一套相对完善的方案,行程一整套技术规范之后,再推广至核心业务中,方便了新技术的布道;

附录:

① 金丝雀发布:什么是灰度发布 如何实现灰度发布 产品角度看待恢复发布

本文作者: arthinking

本文链接: https://www.itzhai.comhow-to-migration-to-microservices.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。