重构项目

最近这段时间工作重点是技术优化,包含代码圈复杂度、代码缺陷优化、项目重构等。重构的项目包括获取机构配置服务、离线对账脚本。获取机构配置每天 4000W+ 访问,对账脚本又涉及到大量资金,重构这些项目困难重重。


重构原因

既然服务这么重要,出错容忍性这么低,为什么要进行重构?

以获取机构配置服务为例,之前存储使用 MySQL, 保存了 5K+ 机构、1W+ 个性化配置信息。在业务高峰期 DB 物理机 CPU 接近满载。为了满足后续业务增长,需要将配置信息迁移到 KV 服务。KV 相比 MySQL 性能更好,同时支持多地容灾。重构之后收益较高。

再比如历史对账脚本使用了 Python、Shell,代码中硬编码了 MySQL 的 IP 端口。从安全和质量的角度来看存在很大问题。在部门的推进下,对这部分代码也需要做改造。

一般项目重构有这些原因:

1、系统容量无法满足业务增长,需要优化服务性能。系统不支持横向扩展,不能通过扩容解决。比如 MySQL 配置库读的是一组 DB,但 DB 的内存、CPU 会有上限。

2、系统架构满足不了新产品需求,需要重新设计增强扩展性。比如之前的业务逻辑是 hardcore,后面又需要针对不同的场景进行个性化,这样整个系统可能需要重新设计。

3、安全和质量原因,需要使用更规范的实现。很多项目在上线之初快速迭代,忽略了代码质量、安全风险。项目里大到架构设计,小到使用组件的方式、编码原则都可能都存在安全和质量问题。

4、旧组件下线和迁移,不可抗力,各种组织里反复造轮子屡见不鲜,旧轮子不维护,新轮子强制上线替换。


重构原则

在重构时,我们应该遵循什么原则来变更?下面对实践中遇到的问题和经验进行总结。

一、可验证原则

a. 变动逻辑的关键日志、监控,执行流应符合预期。比如新增一个逻辑分支,上报的监控变化一定和改动一致。

b. 新旧逻辑的结果对比,结果应完全一致。

业务代码里需要针对这种验证场景写对比逻辑,第一步双读加入监控进行对比,第二步等线上跑一段时间数据完全一致,再切换为新的读分支上线。

二、最小改动原则

如果改动过大,在排查问题时都无法用控制变量法筛选。

a. 另起炉灶,使用新的函数、文件重构。比如重构获取实名的函数 GetRealName,有多处地方调用。可以新写一个 GetRealNameV2 放到 GetRealName 函数中进行替换。

b. 现在的方案是否是最好的,能否废弃掉用更简单的方案。当项目越来越臃肿,可能背离了之前的初衷。回顾一下也许已经有了更简单的方案,使用这种方案也许是更小的改动方案。比如之前使用脚本和机构进行对账、退款,现在已经有了 API 的方式,机构直接使用 API 退款即可。

三、灰度升级原则

升级时需要灰度一部分流量到新服务进行验证,如果流量走到旧系统就使用旧服务,流量走到新系统就使用新服务。 比如实名验证服务升级时,新服务由 CGI 接入层加一个 tag=newrealname 传到后面 AO 层,如果是这个 tag 就使用新的 AO 服务。避免升级出现问题影响太大。

四、可回退原则

a. 重构服务上线后出现异常,应能较快切换到之前的版本。这种机制由变更工具/框架/业务幂等逻辑保证

b. 回退期间的异常脏数据修复。重构服务上线回退时可能出现脏数据,需要提前想好回退后的修复方案。修复方案设计不合理也可能出现问题,需要针对修复方案再修复,套娃开始…


上线 check 事项

  • 机器负载(CPU、内存、IO、GPU、硬盘)性能变化
  • 现网服务监控曲线变化
  • 关键业务日志执行流是否符合预期
  • 热更新 or 冷更新,能否直接替换(例如执行中的脚本不能直接替换)
  • 脚本文件替换后,是否有执行权限


Previous     Next
/
Published under (CC) BY-NC-SA in categories tagged with