微服务接口版本兼容策略 踩过坑才摸透的落地逻辑

上周凌晨三点,我被运维的夺命call炸醒。

原因是电商大促预热,订单服务改了个字段返回,直接把前端的结算页打崩了——整整两小时,大促的预约流量全卡在半路上,团队十几个人熬到天蒙蒙亮才把问题兜住。

事后复盘扯了一下午锅,最后所有人都认的一个核心问题:我们根本没认真做微服务接口版本兼容。

别跟我扯什么业界通用最佳实践,我们之前也照着文档抄,真到业务高速迭代的时候,那些飘在半空的规则全没用。

最先踩的坑:把版本号塞URL里就万事大吉

刚入行做微服务的时候,我跟着网上的教程抄,把所有接口的版本号直接拼在URL路径里,比如/api/v1/user,/api/v2/order,当时觉得这方案简直完美,路径一看就知道是哪个版本,网关改个路由规则就能分流,省了好多事。

真到业务跑起来才知道,这方案的漏洞能漏成筛子。

我们之前就出过这么个事:大促前压测,测试同学把v2的订单接口路由配错了,直接把线上30%的老版本APP流量导到了新接口上。新接口里把原来的orderStatus字段从数字类型改成了字符串枚举,老APP的解析逻辑碰到非数字直接抛异常,结算页直接白屏。

更离谱的是,我们挂在公众号菜单里的去年大促H5,根本没人记得改请求路径,用户点进来直接打早就被下线的v1接口,网关返404,运营小姑娘找过来的时候声音都抖了。

微服务网关路由版本分流架构示意图
微服务网关路由版本分流架构示意图

你看,就算你把版本号放路径里,也架不住人配错路由、漏改老页面、忘了下线旧接口。很多人说要在响应头里带版本号,要在请求头里传版本标识,其实本质都是一样的——你永远没法保证所有调用方都严格按照你写的规则来。

别迷信无限兼容,该断就得断

刚做接口治理那会,我总把“向后兼容”四个字刻在脑门上,怕删了旧字段得罪调用方,怕下了旧版本接口影响业务,结果接口里堆了一堆没人用的冗余逻辑。

比如用户中心的查询接口,为了兼容三年前的某个合作方的旧系统,我们在返回值里留了个叫user_level_old的字段,那个合作方两年前就换了新系统,根本没人调这个字段了,我们还一直留着。每次改用户中心接口,都要反复确认这个字段的返回值没动过,平白多了好多测试成本。

不过话说回来,也不是说要把旧版本供起来。

后来我们拉了个调用量报表,把所有单版本调用占比低于0.1%的接口全部列出来,挨个给能联系到的调用方发通知,说两周后下线,发完通知就硬着头皮删了。最后根本没几个人找过来——原来那些我们怕得罪的“重要客户”,早就没人用旧接口了。

接口版本迭代灰度发布操作流程图
接口版本迭代灰度发布操作流程图

说真的,那种不敢断旧逻辑的心理,才是接口版本混乱的根源。你留着一堆没用的兼容代码,最后改接口的时候束手束脚,出了问题还要兜这些历史包袱,算下来根本不划算。

真正的兼容策略,从来不是靠写文档

现在我们团队做接口版本兼容,根本不贴那些飘在半空的最佳实践,全是踩坑踩出来的硬规则。

所有接口的新增字段必须带默认值,绝对不能修改原有字段的语义。比如原来的orderStatus字段是数字类型,你就算要改枚举值,也不能直接把1的含义从“待支付”改成“已支付”,要新加一个orderStatusV2字段返回新的枚举,原来的旧字段老老实实保留着,等旧版本调用量掉到0了再删。

版本分流不能只靠网关,服务入口必须加一层兜底校验。之前的路由配错的事故出了之后,我们在每个微服务的入口都加了版本判断逻辑,如果请求的是v1版本的接口,就算网关把流量导到了新服务,服务自己也会走老的序列化逻辑返回对应格式的数据,不会直接抛类型错误。

所有接口的变更必须同步给所有调用方,没通知的代码根本合不进去。我们现在把接口变更通知做成了合并请求的强制检查项,你要改接口的返回值,就得在MR里附上给前端、给第三方合作方、给内部其他服务的通知截图,少一个都过不了review。

上周我们改商品服务的接口,新加了个goodsTag字段,默认返回空数组,前端就算不处理这个字段也不会报错。灰度的时候先切10%的流量到新版本,观察了三天,报错率比原来还低一点,才全量放开,全程没出任何幺蛾子。

之前总觉得微服务接口版本兼容是个需要搭复杂架构的大问题,踩了几次线上事故才发现,本质上就是别把调用方当自己人,别觉得所有人都会乖乖按你写的文档来。

你写的每一个接口,迟早要面对老版本APP的奇葩解析逻辑,要面对忘了改地址的老H5,要面对根本没人维护的第三方调用。

哦对,最后提个醒。

别等凌晨三点被运维的电话炸醒,才想起要做版本兼容。

那时候赔的钱,够你招好几个专门做接口治理的工程师了。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:微服务接口版本兼容策略 踩过坑才摸透的落地逻辑
文章链接:https://www.itcdj.com/it/131.html