从我接手过的一个项目说起。先上一个无关紧要的图提提神:
随着项目快速迭代,项目代码变得臃肿,数据表已经接近一百张了。其中部分模块代码消耗cpu和内存大,十几个开发人员在同一个工程里面同时开发着十来个特性,系统如下问题凸显:
1. 特性耦合,发版困难
往往一个特性的改动,会牵涉到若干模块,多个特性代码改动重叠,给测试以及合板,发版带来了极大的考虑,降低了发版的效率。
2. 非弹性部署,扩展能力差
有些模块需要消耗大量cpu和内存,有些模块需要支持高并发,有些模块需要很少的服务器资源,由于都在单一的系统中,各个模块之间公用同一套服务器资源,分配不均衡,不能针对具体业务进行合理配置扩展。
3. 系统业务复杂,接手项目困难
在单一的系统中,涵盖了众多的业务,一个新入职的同事,花三个月可能都未必能熟悉所有的模块,模块间的各种耦合更是让人伤神;不敢轻易调整代码,修改一个问题极易引发另外一个问题。
4. 技术升级困难
由于在同一个项目中,技术架构单一,引入一个新技术对所有模块均会有所影响,调整难度极大,增加技术升级风险,整体技术成保守状态,难以升级以适应快速发展的互联网技术。
为此,服务化拆分提上了日程,喵~
服务化拆分流程
在摸透系统里面所有的业务和数据库的前提下,我们才可以进行服务化的拆分。由于该系统在线上运营时间较久,在参与系统迁移的同事继续迭代了若干需求和线上问题跟进之后,对整个系统的业务都了解的前提下展开服务化拆迁工作。
先梳理各个模块的数据模型,然后确定每个模块的职责,从而可以梳理清晰各个服务的边界。
1. 解耦老系统外部关联
实际的业务场景和系统交互异常复杂,在这里我简化成以下模型进行说明:
根据确定下来的服务的职责和边界,创建新服务程序和数据库,在新服务中约定B、C接口,把老系统中对外依赖A全部转接到新系统,新系统通过编写的路由器,把请求路由到老系统。
之所以把外部系统关联解耦放在第一位,是因为外部系统对接需要协调对应的项目组配合整改,周期不可控,需要先把这部分不可控的先完成上线,方便后续系统内部模块快速拆解上线。
2. 解耦老系统模块间关联
把老系统模块间直接调用A,提升到rpc或者http调用B,对外暴露接口,打断原有模块间业务层或者数据层的直接调用;
原有系统数据库sql关联查询需要按照模块进行拆解,避免跨模块表关联操作;
3. 程序迁移到新系统
按照模块,把相关程序迁移到新系统。
在做解耦老系统模块间关联和程序迁移的时候,需要对老系统业务有深刻的掌握,清晰数据库所有表和字段的作用,以便能快速迁移。
4. 老系统数据全量迁移
把老系统中的所有数据,通过脚本直接迁移到对应新的数据库中。至此,所有业务数据的写入和读取都是基于新服务的数据库了,从把老系统迁移到了新系统。
关于服务化拆迁的灰度上线
根据系统的业务,制定对应的灰度上线策略。由于我们系统整个业务是围绕着产品来开展业务的。所以可以在灰度发布(金丝雀部署①)的时候,发布灰度测试产品,将白名单用户流量打到新版本的服务器分组上面进行验证。待验证没有问题之后,再逐步开放给全量用户。
在验证期间,旧版本如果需要继续流入业务数据,所产生的新的和改动的业务数据需要再次增量迁移到新数据库中。这样会增加增量数据迁移的工作量,容易出错。我们在升级的过程中停止了老版本系统业务数据入库:
其中灰度测试用户产生的数据只存在于新数据库中。
如何给快速迭代的系统进行拆分
一般互联网企业版本迭代速度都比较快,所以系统迁移的速度一定要迅速。如果周期太长,一个大的需求下来,系统改的面目全非系统迁移的相关工作就得重头再来了。
为了能尽快推进系统拆分,总结以上流程,我们要考虑如下五个步骤:
- 需要外部项目组配合的事情先处理完:创建新服务,进行依赖迁移(迁移外部系统接口依赖,迁移外部消息依赖);
- 接口系统内模块间依赖,定义好服务的职责和边界;
- 快速迁移模块到新服务,同时进行数据迁移,进入灰度测试环境;
- 灰度测试验证完毕,迁移增量数据到新数据库,全量用户迁移至新系统;
- 线上稳定后,下线老系统,回收相关运维资源。
迁移之后要继续完善的事情
- 跟上服务化技术配套:服务拆分之后,系统的运维需要辅助额外的代价,维护和测试难度几何级别增加,我们必须要对应的配套技术:自动化测试,持续集成,自动化部署,配置中心,任务中心,日志监控等;
- 分布式一致性事务问题:为了解决此类问题,我们可以通过业务补偿、可靠事件模型,TCC模式进行开发。
系统迁移工作中带来后续工作的启发
- 即使是没有做服务化拆分,系统间各个模块也要职责边界定义清晰,梳理清晰业务模型,保证模块间的低耦合,以及模块的高内聚;
- 尽量避免过多的数据表关联查询,把数据库当成存储数据的介质,业务逻辑转移到程序中实现,这也为后续分库分表,服务化拆分做好了准备;
- 提前准备服务化配套技术,重视底层平台大家。强大的底层平台支撑,帮助我们填平前人已经踩过的坑:灰度发布,服务升级回退,服务注册发现,熔断降级,自动化部署等;
- 服务化之后,新技术尽量从边缘业务进行尝试,积累相关的迁移,服务化,运维问题,构建了一套相对完善的方案,行程一整套技术规范之后,再推广至核心业务中,方便了新技术的布道;
作者:彭展旋,来自金蝶随手记的后端开发工程师,目前做项目管理相关工作,逐渐转型架构,在服务化、分布式事务、p2p金融系统设计、互联网资讯系统等领域有相关经验。
【本文来自51CTO专栏作者张开涛的微信公众号(开涛的博客),公众号id: kaitao-1234567】