众所周知,改造遗留系统并非易事,如果该系统没有良好的架构和编码,那么在这基础上做功能升级改造,往往比做全新系统更加费时费力。我的团队最近承接了一个这样的平台升级改造项目,该平台前后已经历四五家供应商历时七八年的不断修改,可维护性极差。在进行升级改造的同时,我们更“有幸”直接承担了该系统的各项线上运维工作,真真切切体验了陷入“软件泥潭”的感受。
一、那些令我们难忘的经历
在项目一开始,便得知该系统前团队合同已到期会直接撤出,于是我们快速进行了交接,对系统做升级改造之前,先展开运维工作。以下为我们经历的几个片段,该系统的威力略见一斑。
1)“定时炸弹”
系统里有这样一个功能,可以定时修改首页某区域的内容。有这么一次,运营人员通过后台上传要修改的内容后,发现上传错了,但系统却没有提供删除和更新已上传内容的功能,好在可以修改定时时间,于是运营人聪明地把定时时间设置为一年后生效,从而避免了系统首页被改为错误信息。一年后本团队接手了,首页莫名被修改,原本设置该定时任务的人员早已离职,留下我方研发加运维人员努力排查问题至深夜。
2)“扯谎”的流水线
在交接运维工作时被告知客户需要频繁做各种活动,每次活动都是要做代码修改和重新上线的。本团队一度庆幸该系统尽管老旧,但还是可以通过Jenkins进行上线工作的。
但接手后发现我们“天真”了,该系统由4个子系统约二十多个单独部署的服务组成,使用的语言和框架各不相同。当第一次用流水线进行上线工作时,我们以为点了按钮就大功告成了,结果发现最后只有少部分服务部署提示成功,而更过分的是,这些提示成功的部署实际有可能是失败了,而一些提示失败的实际上却是部署成功了。当我们联系前运维团队时,被告知由于年久失修,这些流水线有的能用,有的不能用,有时好用,有时不好用,上线时候让开发备着。为了不影响第二天白天的正常使用,我方研发加运维人员上线到天明。
3)尴尬的日志和难缠的注释
该系统常常出现一些不大不小的错误,不致命但是会被客户业务部门投诉。例如线索模块负责处理线索数据并向下游传送,每周总会莫名其妙丢失几条数据,于是我们展开了问题排查工作。首先就是去查看日志,当找到处理线索的日志后,我们震惊了,只见日志里满屏显示着大写的“END”,既没有时间信息也没有相关处理的信息,只是每条数据成功处理完print “END”,找不到任何有用信息。
当我们去翻看代码时,名不达意自是意料之中,好在有注释。不过注释是乱码,这自然难不住我们,修改编码嘛。修改后又惊奇的发现,一部分注释变成中文可读了,而另一部分却变成了另一种乱码,不管怎么改,总是只有一部分注释变为正常,其他仍为乱码。没想到之前的几波研发团队写注释竟然还使用各自不同的编码。
二、原因初探
那么这套系统怎么会发展到如下境地呢,冰冻三尺,非一日之寒。从我们最近的观察,可能有以下几点值得注意:
1)缺乏长远的规划,各种“债”不断堆积
企业的复杂性,使交付团队处在一个艰难的环境,面对业务侧频繁的、紧急的业务需求,交付团队经常靠技术人员强行对应,导致了各种临时方案不断堆积,各种“债”也随之积攒,系统变得越来越难以维护。
另一个现象是,由于系统各种依赖关系太复杂,每一家新供应商基本都不愿去修改或优化之前的代码,做功能时候都只增不减。以至于系统管理后台出现出现多个同名的模块的诡异现象,其功能又全然不同,完全分不清楚哪个是在用的。久而久之,该系统的运营工作难度也越来越大,换了运营人员肯定玩不转。
2)功能不够运维凑
由于系统功能不够闭环,外加开发阶段过后只剩下运维人员支撑,导致了很多紧要需求通过运维人员改库来实现。当通过改库和临时修改代码来应对需求变成了日常例行操作,整个系统也变得更加脆弱了。
三、应对策略与建议
最好的策略自然是不要过早承接遗留系统的运维工作,至少要等升级改造工作开展到一定阶段,新系统上线后再去承接。但现实往往骨感,如果不得已需要立刻交接,那么建议至少做好以下几点:
1)拉长交接期,在交接期做足功课
将交接列表做得详细一些,并做好交接期间的日程安排,确保双方团队有充足的沟通,从业务和技术层面都有详细的讲解。交接列表参考示例见文末附录,如果项目使用到了一些看板或相关需求开发管理工具也注意一并交接。
对于交接列表中的文档,很可能对方缺失严重,那么一方面是需要让对方尽力补齐相关文档,另一方面则要针对列表中的各项专题开展交接沟通会,尽量获取到更多的知识,在交接过程中注意做好总结。
2)确保开发人员的可调试环境能正常运行
这点很重要,尽管在交接阶段已经拿到了大量文档,但文档的内容和当前代码真的一致吗,紧急出现的BUG如何快速排查和修复?这些终究需要可运行可调试的代码来给出答案。以本项目为例,交接期仅有Tech Lead和一个运维同事开展与前团队所有的技术和运维交接工作,面对多种语言多种框架实现的各类代码有些力不从心,好在果断要求对方协助,在我们的研发机器上实现各类代码的运行和调试。交接完就立刻赶上双十一活动上线,结果到了凌晨抢购时间点,产品购买页面的购买按钮仍是置灰状态无法点击,于是现场调试,发现了系统处理时间的BUG并及时修复,才使业务未受到明显影响。
3)完善监控和日志功能,变被动为主动
这点不用过多解释,通过对监控的完善和日志的完善,使团队能够及早发现系统的各种问题,在出现异常时能够追查原因,不至于手足无措。
4)与前团队维护好关系
虽然这不是一个技术举措,但有时候却非常有效,毕竟前团队经过摸爬滚打,已经熟悉了这个系统的秉性。当遇到一些紧急问题时候,他们的一句建议可能省去一天的错误排查。
四、后记
尽管这样一个“软件泥潭”让团队的行动很艰难,但我们对各种企业级问题的处理和解决增长了经验,我想团队中每个人都会从中有所收获。在系统运维工作顺利展开后,团队终于开启了遗留系统改造之旅。
附录1: 交接列表示例(设计与开发)
类别 | 内容 |
项目管理 | 项目日程 |
会议记录 | |
体制图 | |
项目要件 | 业务功能清单 |
业务流程图 | |
需求变更记录 | |
操作说明书/用户手册 | |
常见问题一览 | |
界面设计 | UE设计稿 |
高保真画面设计稿 | |
需求变更一览 | |
系统设计 | 系统架构设计图 |
部署架构图 | |
DB关联图(ER图)和DB详细设计 | |
系统间集成关系图 | |
对接系统一览表和对接系统接口清单 | |
开发制作 | 源代码 |
代码运行说明 | |
测试 | 系统测试用例与系统测试报告书 |
性能测试用例与性能测试报告书 | |
用户测试用例 | |
用户测试签字 |
附录2: 交接列表示例(运维相关)
类别 | 内容 |
上线相关 | 上线判定表 |
上线操作记录 | |
历次上线版本说明 | |
临时对应体制 | |
基础设施 | 硬件资源一览 |
软件资源一览 | |
服务器/系统账号权限 | |
系统工具 - 付费/免费软件 | |
运维体制 | 运维工作一览表 |
近半年运维工作应对流程 | |
运维体制 | |
故障对应流程 | |
SLA(服务水平协议) | |
DEVOPS(开发运维一体化) | CI/CD工具与使用 |
监控工具 | |
备份管理 | |
代码库与分支管理 | |
数据库相关配置与策略 |