大型线上系统迁移为分布式系统案例

背景

我所在的部门其中重要的一项工作就是对接社区项目新的业务需求,社区项目已经维护N多年了。到14年初的时候社区的解决方案中已经有一百多个工程,每打开或编译一次解决方案都需要等很长的时间。当时就出现这样的情况,几乎没有项目经理能够面面俱到的理清楚社区解决方案的所有代码。同时,在现有社区上做简单修改也是一件很麻烦的事情,而且每次升级社区都会很危险,整个社区项目正在走向腐朽。在这样的情况下,部门总监决定对现有社区项目迁移为分布式系统。

为什么是分布式系统

社区之所以代码量大是因为业务逻辑多、杂并且多种业务之间的代码相互引用,所以明确业务主线、分拆业务主线、降低业务主线之间的耦合度成了首要的任务。分布式系统恰巧能很好的为分拆业务主线,协调业务系统交互提供友好的指导。

最终社区分拆为游戏、计费、安全、推广、账号五大业务系统。每个系统提供UI功能站点(UI功能站点的特点是提供可供用户使用的功能界面,并且包含业务逻辑实现),同时为了便于其他业务系统使用其业务逻辑,每个系统还需要提供业务服务站点。服务站点分为两类,一类是可调用其他服务站点的interface站点,还有一种是不可调用其他业务系统的module站点,这样做的主要目的是为了使接口站点、页面站点的调用关系清晰,便于以后的开发和维护。

迁移中可预见的问题

由于社区是线上系统,所以大的改动会带来发生线上故障的风险。同时在迁移过程中产品部门会不断的提出新的需求,产品的需求的优先级非常高,换句话说我们一边要做迁移的工作一边还要对接新需求。最重要的是部分代码的代码结构会变,简单的代码合不能够解决问题,某个时间段内需要对接两份代码。当然我并不是在叫苦,我只是想说整个迁移的过程会很痛苦。

迁移过程

第一阶段

这一阶段的主要任务是分拆代码,将每个子系统原有的代码移到新的解决方案中,如果需要调用其他子系统的代码则跨解决方案引用老的工程。这一阶段特点是不对对现有的代码做太多的改动,只是简单的把之前的代码移到新的工程里并改动类的命名空间,在这一过程中如果有新的需求需要对接两份代码。这一阶段开发完成后,需要QA人员测一遍所有业务流程并将新代码编译的组件上传到生产环境。

第二阶段

 这一阶段的主要目标就是由引用老的工程改为调用其他业务系统提供的接口并为其他系统提供接口。首先,以业务系统为单位,找到所有引用其他业务系统的代码,并整理成文档。紧接着就是在会上相应子系统的项目经理记录都有哪些系统用到自己负责的系统,并记录调用自己功能的业务流程,还需要消化并剔除重复的需自己提供的接口。接下来的工作就是提供接口了,各个系统的开发人员开发相应系统的接口。这一阶段开发完成后,需要QA人员测一遍所有业务流程并将新的代码上传到生产环境。

为了便于其他系统的接入,每个接口站点需要提供一个SDK,SDK的主要工作就是为调用网络接口和将返回值映射为.NET对象,这样一个子系统想使用其他系统的功能就非常方便,这也是社区为SOA中高互操作性做的努力。

这样保持业务的事物性

当各系统的QA人员测试完个接口的功能和压力之后,各系统供用户使用的UI站点就需要移出对老工程的引用,改为调用相应的接口了,这时候我们碰到一个问题,就是现有的系统不能够支持事物,本来想引入WS-*,但是WS-*效率实在太低了点,结合我们当前实际情况,我们引入了重试以保证每次业务流程都一定能完成,即如果调用相应的业务系统,调用不成功或者业务系统返回的失败,重试服务就会在两天之内调用16次相应的接口以保证确保通知到了该系统。

为什么要分为两个阶段

可能有人会问,为什么非要分为两个阶段呢,并且每个阶段都需要上生产环境,干嘛不直接改完之后上传到生产环境。其实这样做的目的是为了平摊风险,将风险平摊到每个阶段。这里的平摊风险并不是上到生产环境就没风险了,分两个阶段迁移,每一阶段的故障要低于无阶段迁移,避免因线上问题过多而导致必须回滚生产环境版本的情况发生。

末尾

社区迁移完成之后,研发的并行度提高了,每个系统可以单独进行伸缩。从项目经理的角度来看,负责的业务流程和项目清晰明确。从开发人员的角度来看,所面对的项目不复杂。所以说不管是从项目上讲还是从管理上都达到了松耦合目的。

posted on 2015-03-23 20:01  朝曦  阅读(2988)  评论(7编辑  收藏  举报

导航