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

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

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

[[235197]]

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

1. 特性耦合,发版困难

往往一个特性的改动,会牵涉到若干模块,多个特性代码改动重叠,给测试以及合板,发版带来了极大的考虑,降低了发版的效率。

2. 非弹性部署,扩展能力差

有些模块需要消耗大量cpu和内存,有些模块需要支持高并发,有些模块需要很少的服务器资源,由于都在单一的系统中,各个模块之间公用同一套服务器资源,分配不均衡,不能针对具体业务进行合理配置扩展。

3. 系统业务复杂,接手项目困难

在单一的系统中,涵盖了众多的业务,一个新入职的同事,花三个月可能都未必能熟悉所有的模块,模块间的各种耦合更是让人伤神;不敢轻易调整代码,修改一个问题极易引发另外一个问题。

4. 技术升级困难

由于在同一个项目中,技术架构单一,引入一个新技术对所有模块均会有所影响,调整难度极大,增加技术升级风险,整体技术成保守状态,难以升级以适应快速发展的互联网技术。

为此,服务化拆分提上了日程,喵~

服务化拆分流程

在摸透系统里面所有的业务和数据库的前提下,我们才可以进行服务化的拆分。由于该系统在线上运营时间较久,在参与系统迁移的同事继续迭代了若干需求和线上问题跟进之后,对整个系统的业务都了解的前提下展开服务化拆迁工作。

先梳理各个模块的数据模型,然后确定每个模块的职责,从而可以梳理清晰各个服务的边界。

1. 解耦老系统外部关联

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

根据确定下来的服务的职责和边界,创建新服务程序和数据库,在新服务中约定B、C接口,把老系统中对外依赖A全部转接到新系统,新系统通过编写的路由器,把请求路由到老系统。

之所以把外部系统关联解耦放在第一位,是因为外部系统对接需要协调对应的项目组配合整改,周期不可控,需要先把这部分不可控的先完成上线,方便后续系统内部模块快速拆解上线。

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

把老系统模块间直接调用A,提升到rpc或者http调用B,对外暴露接口,打断原有模块间业务层或者数据层的直接调用;

原有系统数据库sql关联查询需要按照模块进行拆解,避免跨模块表关联操作;

3. 程序迁移到新系统

按照模块,把相关程序迁移到新系统。

在做解耦老系统模块间关联和程序迁移的时候,需要对老系统业务有深刻的掌握,清晰数据库所有表和字段的作用,以便能快速迁移。

4. 老系统数据全量迁移

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

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

根据系统的业务,制定对应的灰度上线策略。由于我们系统整个业务是围绕着产品来开展业务的。所以可以在灰度发布(金丝雀部署①)的时候,发布灰度测试产品,将白名单用户流量打到新版本的服务器分组上面进行验证。待验证没有问题之后,再逐步开放给全量用户。

在验证期间,旧版本如果需要继续流入业务数据,所产生的新的和改动的业务数据需要再次增量迁移到新数据库中。这样会增加增量数据迁移的工作量,容易出错。我们在升级的过程中停止了老版本系统业务数据入库:

其中灰度测试用户产生的数据只存在于新数据库中。

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

一般互联网企业版本迭代速度都比较快,所以系统迁移的速度一定要迅速。如果周期太长,一个大的需求下来,系统改的面目全非系统迁移的相关工作就得重头再来了。

为了能尽快推进系统拆分,总结以上流程,我们要考虑如下五个步骤:

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

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

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

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

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

作者:彭展旋,来自金蝶随手记的后端开发工程师,目前做项目管理相关工作,逐渐转型架构,在服务化、分布式事务、p2p金融系统设计、互联网资讯系统等领域有相关经验。

【本文来自51CTO专栏作者张开涛的微信公众号(开涛的博客),公众号id: kaitao-1234567】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2019-01-07 08:10:54

微服务单体 Web

2022-08-05 07:37:39

单体架构迁移微服务

2022-12-22 09:00:00

微服务架构

2019-07-31 10:21:15

单体架构微服务

2023-10-24 08:00:00

单体架构微服务

2022-08-22 14:27:30

微服务迁移

2021-02-02 14:39:03

微服务架构数据

2019-09-25 08:57:24

单体式架构微服务

2009-08-06 09:20:30

2023-12-19 22:29:37

架构微服务系统

2022-03-19 16:47:47

WordPress网站迁移服务器

2024-01-26 06:06:26

单体微服务容器化

2020-01-18 09:35:03

微服务团队架构

2023-08-31 17:13:01

架构软件开发

2022-04-11 17:33:29

微服务架构单体

2021-12-08 09:23:39

云迁移云开发云计算

2020-10-30 10:45:04

云计算IT技术

2021-07-07 10:48:00

DigGoWire

2023-02-27 16:24:17

架构开发数字化

2022-08-29 10:35:42

微服务架构单体应用
点赞
收藏

51CTO技术栈公众号