App后台开发运维和架构实践学习总结(3)——RestFul架构下API接口设计注意点

时间:2021-10-10 21:47:50

1. 争取相容性和统一性

这里就要求让API设计得是可预测的。按照这种方式写出所有接口和接口所需要的参数。现在就要确保命名是一致的,接口所需的参数顺序也是一致的。你现在应该有products,orders和customers的数据吧?,它们应该都存在含有id和name的表中。那么不要让一个接口仅传ID而另一个仅传name还有的两个都要传。也不要让一个接口按照/product/ID传参而另一个接口按/ID/customer这样传参。因为作为一个API的使用者我希望以相同的方式访问两个不同的资源。

另外一个保证相容性的技巧是观察你的参数值类型。如果一个接口的ID参数求为整型,那么不要让另一个接口的ID参数为字符串型。因为作为一个API的使用者我不想去猜每个接口的每个参数值类型。

除了需要考虑你的接口如何访问数据以外,你也应该好好想一下你的API如何返回数据以及返回数据格式的统一性。目前在我最近使用的API中就存在一个很大的问题。当开发中用到一个返回数据的接口时,我很惊奇的发现返回结果(XML格式的...我接下来会讨论为什么我将会避免使用它)里面的每个元素都本该都含有一个特定的属性。然而结果是一些元素有那个属性而另一些却没有。我宁愿那个属性是一个空值也不愿意看到完全没有那个属性。原因是如果我遍历每个元素来寻找这个属性,我希望至少能找到它,即使它没有值。然而现在就像是从数据库查出几条记录然后发现有几条数据里面没有某个字段而其他几条却有。然后这就开始让你怀疑查询出来的结果并产生了一个疑问“那些消失的属性是被我弄丢的吗?”

2. 考虑得直爽些

你应该有过打电话给别人让他帮你做一件事时对方很爽快地回复一个“好!”的经历吧?通常这时你会踌躇一下然后去问“你确定会帮我做吧?”。优秀的API不仅会做你想要它执行的操作而且还会额外返回有关它刚执行的操作的相关信息。如果你的某个API是负责创建一个product的,那么就让它执行完创建操作后返回一些有关刚刚创建的product的相关信息,而不是去要求客户端再去发送一个请求来获取你刚刚创建的product的相关信息。因为那样就显得你很没脑子。但是你还是会惊奇地发现有很多API执行完操作后只返回一点像200 OK那样的信息。所以只需要让你的API给客户端返回一些有用而且明显需要的关于刚刚执行的操作的相关信息就可以让它变得直爽。

3. 让API很容易去完成一个请求

你通常是不是更愿意这么做:让别人开车载你去干洗店或者直接让别人开车去干洗店,下车后打开店门走进干洗店,找店员拿完你的衣服然后离开干洗店再开车回到你这儿。所以你的API不要让客户端调用多次只是为了去做一个通常都需要执行的子任务!你可以通过提供默认参数值而且允许客户端可以根据特定请求去覆盖你的任意一个默认参数值来解决这个问题。

我目前一直在用的一个API就让我感到很痛苦而且还很费事时。它本应该设计成只需一个简单的请求就可以创建一个预定产品,而且耗时只需要耗时300-500ms,然而它却设计成需要你去发送7个往返都需要300-500ms的请求。这便使得本来只要300-500ms的进程要花费好几秒!而且这些增加的时间都会被使用这个API预定产品的消费者注意到。

4. 恰当地使用响应

这条建议是建立在前几条之上的。如果请求的操作处理成功了,返回了一个成功像200 OK这样的状态码。如果请求的操作处理失败了,给出适当的像404或500等这样的状态码来表明处理失败了。因为我们想要实现的是客户端在使用API时首先能根据返回的状态码来决定接来下如何去处理具体的返回内容。我现在用的一个API确实是会返回给我一个200 OK的状态码但是他紧接的返回内容是一个处理失败的报错信息。以至于,尽管我知道请求成功了但是我不得不去检查我请求的操作是否真的处理成功了。所以请不要像这样设计。你只需要在一开始就返回一个恰当的状态码后接下来就知道该如何处理了。

5. 多考虑性能问题

优秀的API都是能够很快地处理大量的请求。你处理完一个请求后取得的结果可以直接返回给那些完全相同的请求而不需要重复处理。换句话说,你应该尽可能地使用像服务器端缓存那样的技术。如果一个用户请求product1的信息,然后过几秒又有另一个人也请求product1的信息,这时你就可以将返回给第一次请求的结果同样返回给后来的请求。不需要再次查询仅仅是为了返回你刚才已经查出来过的相同数据。同时也要确保给缓存一个过期时间以免让缓存内容变得过时。

Chargify在这方面就做得很好。我向他们请求一个预定产品时他们能够在200ms左右回复我结果。这是相当快的。而且如果我在一分钟之后再次请求这个预定产品时他们会在97ms内返回给我同样的结果。同时要知道并不是所有的接口和查询都可以像那样设计,但是如果你的数据是不变的或者不经常变,那么就要考虑在你的API使用缓存来加速请求的处理。你的客户端将会因为这爱上你。如果客户端将响应结果缓存在它们自己的客户端缓存里那就能让他们更满意了。

6. 用带有SSL的Basic Auth

你现在有很多种方法来保障API的安全性,例如:Basic Auth(基本认证),Digest Auth(摘要认证 ),OAuth(开放认证),no auth等。当你考虑用哪种方法的时候需要考虑的是认证方法的性能和易用性(像上面的建议5和建议3所说的)。如果你用了SSL的话,我建议你采用Basic Auth方法,因为它很容易部署,而且只需要请求一次而不需要多次(Digest Auth通常都需要至少两次以上的请求才能完成认证)所以性能相对来说也会高些。显然如果你不使用SSL,那么就建议你用Digest Auth或者OAuth等其他的安全的认证方法。

7. 给你的API制定版本

恭喜你!你的API设计的很成功而且在被很多用户使用。现在他们的很多产品和项目开始依赖于你的API。但是你现在需要考虑的是如何在不影响他们使用的情况下去更新你的API。如果你能让不同版本的API相互独立开来,我建议你将版本号作为一个参数或者API命名的一部分。例如:GET /v1/product/id或者 GET /v2/product/id 或者 GET /product/id?v=1。你也可以选择将版本号部署进HTTP请求头,但是无论你采用哪种方法都要确保所有的版本都采用同一种方法。

通过将API用版本号区分开可以让用户一直使用某个版本的API直到恰当的时候再迁移到新版的API。你也可以随时关掉某个版本API而不需要对现有版本的API做任何处理。

8. 使用JSON而不要使用XML

第8条建议是根据我个人偏好提出的。我工作到现在用过很多API,JSON格式和XML格式都有。我会告诉你我觉得JSON格式的更好用。JSON格式通常是更为简洁的(以至于传输的数据量更小),也更容易展现复杂的对象(精确)而且能运行得像其他格式一样好(以至于现在每个人都在用JSON)。XML通常都是很冗余的,还不容易展现复杂的元素而且还需要一个DTD来验证它。所以我将会用JSON格式,如果你想用XML的话那就随便吧。不管怎样,我认为只要你开始用JSON你就会很明显得发现XML的缺点。

总结

我提出的8条建议可以帮你更好地考虑你接下来需要设计的API。API正在改变我们和集成系统的交互方式,所以它的质量就变得尤为重要了。如果你设计API时考虑到了终端用户,那么你就要考虑如何让他们更容易使用,这样你的API才会变得更成功。如果用户用别的API也能完成你的API能完成的事,但是别人的API更容易使用、响应速度更快,用户自然就会去用别人的而不是你的。

所以不要犯这些严重的错误:传参格式不一致,只做简单的响应,对刚刚处理的结果只字不提(不健谈)而且响应得很慢。那将毁了你整个API。如果你的API是你的生意的话,那些错误会让你整个生意黄掉。