zoco

APP API需要同时维护多个版本的一些想法

2018-01-20


第一种形式:

Controller/V1.0.0/
-----------------/UserController.php
-----------------/UploadController.php
Controller/V2.1.0/
-----------------/UserController.php
-----------------/UploadController.php

第二种形式:

Controller/
----------/UserCreateController.php
----------/UserInfoController.php
----------/UploadImageController.php

UserCreateController.php 内容如下:

classUserCreateextendsApiController{
  publicfunctionv1_0_0(){}
  publicfunctionv2_0_0(){}
}

第三种形式:

客户端在做请求的时候在接口中添加version字段,标识出请求的是哪个接口:

api.xxx.com/api?version=v1&… api.xxx.com/api?version=v2&…

这种做起来比较简单也容易理解,但是在你的每个接口逻辑里面都得需要写判断版本的代码了。比如:

if(version == 'v1') {
  do_something_with_v1_style
}else if (version =='v2') {
  do_something_with_v2_style
}

这样的代码看起来感觉很不舒服。而且会维护一大堆的if-else,以后会越来越长。

第四种形式:

客户端在做请求的时候在HTTP HEAD里面中添加API-VERSION字段,标识出请求的是哪个接口:

-H"API-VERSION: v1"
-H"API-VERSION: v2"

这个需要统一做的事情稍微有点多,但之后的接口逻辑会比较好些。在入口的地方获取接口版本,然后把请求分发到对应版本的接口处理器上。

api(req):

if(req.HEADS["API-VERSION"] =='v1') {
  distribute_to_v1_api(req)
} else if (ver =='v2') {
  distribute_to_v2_api(req)
}

第五种形式:

不同版本使用不同的域名,这样:

v1.api.xxx.com

v2.api.xxx.com

域名的方式可以采用下面的两种方式:

1、不同版本的api部署成不同的应用(甚至可以部署到不同的服务器上),彼此间独立,其好处是部署的过程不会影响其他版本api的使用,并且可以减轻单台服务器的负担。 2、部署在一个应用上面,但是和第四种一样,在接口入口出分发到不同版本的接口处理器上进行处理。好处是不同版本间能够直接复用相同的功能。

总结一下:

我个人比较倾向于第一种(xxx.com/v1/、xxx.com/v2/):

在整个产品的生命周期中接口的数目和功能可能会不停的增加,但对于某个接口而言,不会频繁的变动(修改接口的输入输出约定),而增加接口对于老的接口是没有影响的,也就不会到必须升级接口的地步(你的老app只是在用原来就存在的老接口而已,新增加的接口对它没有影响)。

如果你的接口变化已经到了今天v1、明天v2、后天v3的地步,那么得考虑你们一开始对产品的需求是否足够准确了(估计需要维护的接口文档也会让人头疼)。

不同版本接口相互独立在某种程度上限制了你,让你不会随随便便就v1、v2、v3。(当你每天都要用一个新域名的时候你自己一定会不自然的反思是不是变换太频繁了)。

接口版本信息能够直接在url里面体现,清晰易懂,也比较容易做接口调试(没错,给我一个Chrome就够了)。

不同的版本的api应用(或者接口处理器)之间彼此独立,这符合软件工程的低耦合原则。

没有很优雅的设计,只能自己考虑的长远写,接口的代码写的可扩展性高一些。App跟网站不一样,即使你发新版了还是有很高几率用户不买账不更新的。所以最好在最初设计接口的时候就想的长远些,API的URL不能随便动,

所以设计核心业务的API只能考虑的比较清楚了,有些东西刚开始不做但是近期几个版本要做的话就预先留好入口,代码写的可扩展性高一些方便以后兼容,数据库中也可先预留好字段。

对版本接口维护,个人认为是灾难性的。不同版本的业务逻辑,需要操作最新版本的数据结构,同时还要维护各版本的文档,各版本的自动化测试或者人工测试ok。

所以个人认为比较好的做法是,在开始设计的时候,查询类的接口,应尽可能使用被动式提供数据的无状态接口,格式应竟可能使用对象(不使用二维的集合),这样的接口对于扩展字段非常的方便,也很容易做到向下兼容.

操作类的接口,尽可能地将资源分离,比如修改用户信息,跟修改用户头像信息或者修改用户职位信息,这样的接口,尽可能使用独立的资源。 对于实在没有办法需要全面升级接口的。

如果可能,保持原有的业务,原有的接口运转正常。

然后构建一套全新的隔离的接口。

最后做下版本使用监控。当观察到所有用户都使用新版本的客户端的时候,并保持一段时间的时候。放弃对老版本的维护,继而下掉老版本的资源。当然,万不得已的时候,还可以用强制更新。