对于一个成熟的工程项目而言,因为项目未来发展或是和企业内部更深度融合的需要,我们可能需要对既有业务逻辑做很大规模的改动,涉及到多方面的逻辑迁移和代码重构,才能够达到下一代产品所需要的效果。
今天这篇文章,就来剖析一下如何做好这件事情,尤其是在历史积淀非常厚重的场景,需要通过怎么样的手段,把这个问题解决好。
首先第一件事情是,了解背景。为什么要做这件事情,它对于团队和公司的业务价值以及技术层面的价值在哪里?从一个打工人的视角,一个大规模的业务逻辑迁移,背后一定是有大团队甚至公司层面的底层逻辑在牵引,如果作为负责人不去了解底层逻辑,那也就不好把握业务迁移的方向,最终就有满足不了技术跟产品效果的风险。
好比说,从业务角度,通过优化性能和线上表现问题,明确历史遗留潜规则,提升用户使用体验,减少用户适应成本,提升工程项目在公司内部的影响力,成为更加统一化的标准。这些都可能是这个项目做大规模迁移的理由。然后,从技术角度上,比如通过重构代码,整个项目能够呈现更加干净简洁的代码实现,更加统一的关系结构和逻辑思路,更高内聚,更易扩展,提升项目代码和服务架构的可扩展潜力。这些也都是业务迁移工作可以随之带来的技术价值。充分了解完这件事情的背景之后,我们就可以更加精确地下手。
做业务逻辑迁移,最重要的一点是,要维持原先的产品表现。为了达到这个效果,我们可以考虑很多种技术手段,比如代码重构就是一种最直接的方式。但是,除了代码重构之外,有没有更好的方式?比如重新写一个工程,或者把某些模块作为单独的服务拆分出来?或者说,在当前这个场景下,为什么重构既有代码是最好的解决方式?有什么理由可以论证这一点?这些,都是在准备工作过程中需要思考的问题。
有些时候,为了满足咱们负责人自身的技术信仰和控制欲,重写工程就是一种最完美的手段。但是,重写工程耗时耗人力非常大,并且会改变用户习惯,所以现实上不一定是最好的方法。但如果说,既往工程和某些特定的场景耦合度太高,但代码质量太差,导致代码无法拆分,技术层面上完全不满足要求。这个时候,就可以考虑重写,不仅可以实现效果,也可以解决很多以往的技术问题,一举两得。
拆分服务,也是一个可以选择的举措,但前提是要重构的部分是独立的模块,容易被单独提出来。如果说既往的代码关系繁杂,存在很多潜规则,内部之间存在很多一时半会不能厘清的依赖,那么在业务逻辑升级期间,同时盲目拆分服务,也是具有风险的,所以一个合适的举措是先重构既有代码,再在重构的基础上去拆。此外,拆分服务本身也会引入额外的服务架构复杂度,所以一定要明确拆分服务可以解决的问题,比如说加快部署速度,减少非核心模块对L0服务带来的影响,都可以成为拆分服务带来的价值。
所以最终,业务逻辑迁移,还是必然会走到代码重构环节。那么重构要怎么做?怎么样能够保证重构先后,用户体验不受影响?有一个合适的思路是,通过配置开关,控制业务逻辑走到既往的链路,还是升级后的链路。当然在此之前,我们需要了解整个代码的脉络,业务链上每一个环节的职责,然后需要对每个环节构造测试用例,什么场景测什么,以便在重构时候可以随时验证。对于配置的开关,也不单纯是一个true-or-false的粒度,粒度可以设置的更细,更加倾向于一个灰度filter的设计------在业务逻辑的前置判断中,如果灰度则走新的逻辑,没有被白就是走老的逻辑。通过开关机制,我们可以兼容业务迁移过程的各类中间态,从而满足用户无感的需要。
这里需要注意的一点是,由于中间态的存在,那么在内测和灰度过程中,势必有很多需求需要双写到老的逻辑和新的逻辑。多人开发场景下,如果团队内部没有对齐这个口径,那么就会有新老逻辑效果不一致的风险。要解决这个问题,就需要保证团队内部对这件事情也能达成一些共识,尤其是需要同步这次迁移对于团队内成员做开发工作的影响。通过减少口头上的信息差,从而减少代码上的信息差。
之后是迁移的执行。大规模的业务逻辑迁移总是有风险的,因此从产品角度,对核心用户同步风险,做公告周知,对所有用户同步迁移事项以及需要改变的用户习惯,都是一个责任人需要做的事情。在迁移实操方面,也需要做到有内测、灰度放量、全量放量的过程,好比说涉及到数据迁移,放量可以遵循10%->30%->60%的原则,策略方面可以根据用户的体量和不同业务的数据存储量来决定具体放量的内容,这样就兼顾数据迁移的效率和安全性。
当然,比起对外周知风险,对内也需要做好稳定性保障,保障业务逻辑迁移过程中风险尽量减少。首先,我们可以通过一系列业务监控和服务监控来做一个大致的把握,比如业务指标方面观察事务成功/错误率,事务/结果量级的变化,服务监控关注latency、错误日志、错误请求、panic崩溃以及cpu/memory之类通用容器的监控。其次,对于业务效果,我们也可以在某些走新业务逻辑的case里,同时灰度一些用户无感的老业务逻辑流程,做一下abdiff,从而直观对比最终的迁移效果。通过这些手段,就可以在线上迁移之前,尽可能在线下发现更多的问题,减少线上风险。
最后一点,就是大规模的迁移,最好是和原来的效果保持一致,原则上尽量不要引入其他业务机制层面的的革新。用户对于产品的玩法是丰富多样的,甚至比产品更了解产品,比如游戏,玩家的攻略能力永远领先于游戏策划,玩家发现bug的能力永远领先于游戏测试。迁移过程本身就可能会改变很多用户习惯,所以如果迁移之后,还顺带做一些机制上的革新,那就有违背用户习惯的风险,最终就会导致产品表现不符合预期。如果一定要在迁移期间做一些机制上的变动,那么在线下就需要做充分的用户行为调研,否则建议是在迁移之后,根据用户具体的反馈,再选择性下手。