做后端开发这么多年,我见过太多API死于襁褓之中。不是死于性能瓶颈,不是死于并发风暴,而是死于——没有版本控制。
一个没有版本的API,就像一辆没有刹车的赛车。刚开始你觉得自己很酷,跑得飞快。直到有一天你需要改一个字段,发现线上几十个调用方已经开始骂娘了。
今天咱们就来聊聊API版本控制的三种主流方案,顺便吐吐槽。
流派一:URL路径版本 —— 门户型
这种方案的拥趸最多,写出来大概长这样:
GET /api/v1/users/123
POST /api/v2/users
优点?一目了然,调试方便,直接复制粘贴就能测试。nginx配置也简单,rewrite一下就行。
但问题来了——
这玩意儿根本不是RESTful!
Roy Fielding(REST之父)老爷子如果看到你把版本号塞进URL,怕不是要从棺材里跳出来给你一巴掌。在他看来,/v1/这种路径片段代表的应该是资源的层级关系,而不是什么版本号。
当然,实用主义角度来说,这方案确实香。毕竟:
任何不落地的架构讨论都是耍流氓
你跟PM说「这个字段语义变了」,PM只会问「那线上那个还能用吗」。URL版本至少能让PM安心,让调用方放心,让你在改需求的时候不用想着一夜之间同时维护三套接口。
流派二:Header版本 —— 学院派
这种方案的典型写法:
GET /api/users/123
Accept: application/vnd.mycompany.v2+json
看起来很优雅对不对?URL还是那个URL,版本信息藏在header里,多纯粹。
然后你就会遇到以下场景:
- PM说「帮我在浏览器里调试一下这个接口」
- 测试说「Postman怎么设置这个header来着?」
- 运维说「nginx日志里我想看到版本号方便统计」
优雅是需要代价的。
很多CDN和网关不支持自定义header透传,或者需要额外配置。等你排查一个线上问题,发现是某个中间件把你的Version header给吞了,那酸爽,比吃小龙虾被辣到还难受。
这种方案适合那种「我就是要教条地遵循规范」的团队,以及对API美感有执念的架构师。普通业务团队,建议绕道。
流派三:Query参数版本 —— 折中派
方案如下:
GET /api/users/123?version=2
这不是跟URL路径版本差不多吗?
区别在于,这种方案下默认是不带version参数的,会走最新版本。带version的请求才走对应版本。
这种「默认最新,逐步迁移」的思路其实挺聪明的。新调用方不用关心版本,老调用方带上自己的版本就行。
但问题也很明显:
// 你永远不知道一个URL会被怎么调用
/api/users/123?version=2&page=1&pageSize=20&sort=name&filter=active&source=app
query string的长度会像吹气球一样膨胀,有些网关对超长query string还有限制。更重要的是,缓存。不带版本和带版本的请求会被视为不同的URL,缓存命中率和开发体验都会打折扣。
我的建议:混合双打
说了这么多,到底怎么选?
我的经验是——URL大版本 + Header小版本。
什么意思?
比如你做了不兼容的大改动,需要同时跑v1和v2两套接口,用URL区分:
/api/v1/users
/api/v2/users
而v2内部的小改动,比如加了个字段、加了个返回值的可选属性,通过header或者约定来控制:
GET /api/v2/users
X-API-Features: extended-profile
这样既能让调用方清晰看到自己在用哪个大版本,又能在小版本内有足够的灵活性。
最重要的:提前设计!
不管你选哪种方案,在API设计的第一天就把版本策略定下来。
我见过太多项目,上来就写:
POST /api/addUser
然后产品说「加个批量接口」,于是:
POST /api/addUsers
再然后「再加个根据手机号查用户的接口」:
GET /api/getUserByMobile
等你回头一看,这个API命名风格之混乱,堪比娱乐圈的艺名。
所以,趁早定好规矩:
- 版本号放哪、怎么命名(v1还是1.0)
- 什么情况算小版本、什么情况要大版本升级
- 旧版本保留多久、怎么通知调用方迁移
这些规则写进你的API设计规范里,比你以后手忙脚乱强一百倍。
最后的吐槽
API版本控制这件事,说到底是在和「变化」和解。
产品会变需求,业务会变模式,技术会变架构。你的API终有一天会被废弃,你的URL终有一天会被重构。但在那一天到来之前,一个好的版本策略,至少能让你睡个安稳觉,不用凌晨三点被电话叫起来处理线上事故。
小龙虾我个人的血泪教训:能URL版本就先URL版本,别为了所谓的「规范」给自己找麻烦。等你真正需要「纯粹」的RESTful的时候,你自然会知道。
毕竟,代码是写给人看的,顺手比正确重要。
下期见!