版本控制,没有你想的这么简单

时间:2022-04-11 06:42:57

用产品思维设计API(三)——版本控制,没有你想的这么简单 前言

最近公司内部在重构项目代码,包括API方向的重构,期间遇到了很多的问题,不由得让我重新思考了下。
- 一个优雅的API该如何设计?
- 前后端分离之后,API真的解耦分离了吗?
- 不断的版本迭代,API的兼容性该如何做?

ps.这里所说的API仅为Web API,提供APP\WEB开发使用。

年前,我司内部的接口已经进入了一个完全的重构阶段,参考了市面上各大平台的API和文档,自己也总结出了很多的心得。这里向大家分享一下,接下来一个月,我们向从下面几个方面向大家介绍一个优雅的API(至少我认为挺优雅)该如何设计。

RESTful就是个骗局 ()

数据解耦,才是前后分离的本质()

版本控制,没有你想的这么简单()

随意定义错误码,你还在这样干?

安全,就只能用HTTPS?

ps. 打一个广告,公司内部现在在招聘各种技术岗位,Java、Android、前端等,待遇保证能让你涨30%,有兴趣的朋友可以加韬哥的微信(微信号:stchou_zst),二维码在文章最后。

业界目前常用的做法有哪些?

在RESTful API领域,关于如何做版本控制,目前业界比较主流的有3种做法:

URI版本控制

即在URI中直接标记使用的是哪个版本,无版本号URI默认使用最新版本。如下:

http://xianlinbox/api/customers/1234 http://xianlinbox/api/v3.0/customers/1234

好处:
直接可以在URI中直观的看到API版本,
可以直接在浏览器的查看各个版本API的结果

坏处:
版本号在URI中破坏了REST的HATEOAS(hypermedia as the engine of application state)规则。版本号和资源之间并无直接关系。

URL参数控制

即在每个请求后添加一个version参数,表示请求的是哪个版本。如下:

http://server:port/api/customer/123?version=2

这种做法其实就是URI方式的变种,好坏处也都一样。

Mdedia Type控制

即在HTTP请求的header中使用Media Type标记该请求想获取的资源, 同样的可以不设置或设置通用的Media Type表示最新版本的API。

GET /customer/123 HTTP/1.1 Accept: application/vnd.xianlinbox.customer-v3+json HTTP/1.1 200 OK Content-Type: application/vnd.xianlinbox.customer-v3+json {"customer": {"name":"Xianlinbox"} }

好处:
遵循了REST的设计风格(tencent的基本都是这个风格)

坏处:
版本不直观,需要能设置header的client才能调用查看该API的效果。

这么多API版本控制的方式,其实看起来都差别不太多,用起来都区别不大。选择这么多并不是好事,我们要选择哪种呢?

等等,我们做版本控制要解决什么问题?

APP版本迭代之中,需求更变,API接口洗发的逻辑发生了改变,为了兼容不同版本的APP使用,才能需要对API进行版本控制。

如:

/getUserInfo (获取用户信息)接口

返回信息

{ nikeName : "诚壹小主", sex : 0, email : "test@chengyiwm.com" }

现在需求有变,这个接口的下发信息有变,需要增加一个头像字段,在APP上显示用户的头像。

{ nikeName : "诚壹小主", sex : 0, email : "test@chengyiwm.com", avatar : "http://www.test.com/pig.png" }

只是增加一个avatar字段,对于客户端解析JSON来说,并没有影响。困难就困难在,很多情况下,我们并不是要增加一个字段,而是改变一个现有的字段返回的信息。

如,这里需要将sex的内容从”0”改为”female”

{ nikeName : "诚壹小主", sex : "female", email : "test@chengyiwm.com" }

映射的Bean属性变了,没法继续使用这个接口了,必须升级。我们可以用上述的三种形式的任意一种。如:

/v2/getUserInfo

问题是解决了,但是,又引入了新的问题。我们的更变需求仅仅有修改这么一个接口而已。其他的接奥口内容并没有发生变化,路径和版本号都不需要修改。这么一来,经过几次迭代就会出现下面几种问题:

客户端请求的版本号混乱,冗余

异步更新版本号: /getOrder /getAppList /getProductList /v2/getUserInfo (与上面的是不是一套API,能不能混用,搞不清楚) 同步更新版本号: /v2/getOrder (没更新) /v2/getAppList (没更新) /v2/getProductList (没更新) /v2/getUserInfo (更新了sex字段)