这个项目,我刚接到手的时候,差点骂娘。不只是技术上的难搞,更多的是历史遗留的那些扯皮烂事。
接手:为什么叫“杨过”和“继承者”?
我当时被叫过去,是因为两个核心系统数据根本对不上。公司里有两个派系,一个管老资产的,我们内部叫它“继承者”(Heiress),因为他们掌握着所有客户的核心历史数据,系统用的是七八年前的Java框架,结构稳固,但是跑起来慢得像蜗牛。另一个派系,是搞新业务,主打移动端快速迭代的,我们管它叫“杨过”,它追求快,用的是时髦的Python和一些轻量级框架。这两个系统,本来应该互补,结果因为历史上的资源分配问题,两边谁也不服谁,都想把对方的功能集成到自己这边,导致功能严重重叠,接口命名乱七八糟,逻辑更是一团麻。
杨过那边搞了个用户登录,继承者这边也搞了一个;杨过改了用户画像标签,继承者那边完全不知道,自己还在跑旧的清洗逻辑。老板终于忍不了了,把这摊子扔给了我,要求我把这两个狗皮膏药系统揉成一个,对外只暴露一个统一的API。这就是《Heiress杨过游戏》的由来,听着像游戏,实则是地狱难度。
实践过程一:硬着头皮扒拉老系统
我接到的第一步任务,是清理门户。我先从“继承者”系统下手,没办法,它是数据的源头。那个系统,文档基本没有,全靠代码里自己加的注释。我花了整整一个星期的时间,干了这么几件事:
- 定位核心冲突: 我拉了个详细的大表,把两个系统里所有涉及“用户身份”、“订单状态”和“数据写入”的接口全部列了出来,然后逐个比对逻辑和数据模型。
- 强制抽象接口: 我发现继承者那边的数据模型虽然老,但好歹是全的。问题是它开放出来的接口太原始了,比如查一个用户的基本信息,要调用三个不同的接口才能拼齐。我决定不碰它的底层代码,而是在它的外面套一层适配器。
- 摸清写入路径: 这是一个大坑。杨过那边为了快,直接写数据库,而继承者那边通过消息队列同步数据。我必须截断杨过那边的直接写入,让所有数据流动都必须走继承者的消息队列,保证数据权威性。
实践过程二:给杨过“戴上金箍”
继承者系统虽然慢,但它是权威。杨过系统虽然快,但它做事不过脑子,缺乏验证和权限控制。我的第二步,是改造杨过,给它加上统一的权限和验证机制。
杨过那边的工程师,一开始很不配合,觉得我是在添乱,硬生生拖了我两个星期。我没跟他们多废话,直接开了个独立的微服务,用Go语言写了一套轻量级的API Gateway。为什么选Go?因为快,部署简单,最适合用来当这个“传话筒”和“守门员”。
我的做法是:
- 所有请求先过Go网关: Go网关只干两件事:一是验证用户的身份令牌,二是确保请求的数据格式符合新的规范。
- 适配器调用: 网关内部内置了继承者的适配器。当杨过系统发起请求时,它调用的不再是继承者的原始接口,而是我的Go网关。Go网关收到后,将请求重新封装成继承者能懂的格式,再扔给老系统处理。
- 数据统一出口: 继承者系统返回的数据结构也是乱七八糟的。Go网关拿到原始数据后,会强行统一模型,只返回给杨过系统需要的那几个字段。
这层网关,硬是把两个系统的差异给抹平了。杨过系统以为自己在跟一个新潮的API打交道,而继承者系统以为它只是在正常处理请求。
最终实现:系统稳定,我却被隔离了
经过前后两个多月的反复磨合和调试,新的统一接口终于上线了。一开始小问题不断,主要是数据格式转换上的细节错误,我那段时间基本是住在机房里,随时准备回滚。但最终,所有业务都切换到了这个新的“中间层”上。最大的成就感是,以前两个团队为了一个字段的定义能扯皮一整天,现在他们只需要遵守我定义的统一规范,矛盾一下就少了一大半。
我刚把系统跑稳,松了口气,结果那天公司组织体检,发现我血糖高得离谱。医生直接建议我在家静养,把我强制隔离了一段时间。我当时还想着,这下清净了,可以好好睡个觉了。结果,我这边刚走,杨过那边为了赶新功能,又绕过了我的网关,偷偷加了个数据库直连,导致数据同步又出问题了。我远程一看,气得不行,赶紧打电话回去,要求他们立刻回滚。
这事告诉我一个道理:技术架构能解决眼前的问题,但解决不了人性的偷懒和内斗。你建立了一个规范,总有人觉得绕开规范能更快。现在系统虽然稳定了,但我的这个网关,必须安排专人盯死,不然他们随时都会给我搞出新的“杨过”或者“继承者”出来。我把这套经验写下来,就是想说,做技术实践,很多时候,你得先当好“消防员”和“政治家”,然后才能当好工程师。