分布式平台下 API 设计浅谈

1,297 阅读4分钟

昨天写了一篇《如何做系统重构(上)》,本来今天应该推出下半部分的,内容我也写好了,就等时间到了就推送。不过后来想想,还是先换换胃口,将另外一个话题先聊了来。

我们都在做分布式,也由于分布式,外部第三方对接,导致了我们在不断的对内提供API,对外暴露API。从几年前,自己冲着第一线写API,到带着团队一道写,到现在更多的是和团队一道执行API的规范,也积累了一些想法,今天继续抛砖引玉,谈谈我对分布式平台下,微服务架构下设计API的思路。



1.  接口文档先行

当需求确认后,先定义接口,确定数据结构,协议和入参,Response等需要在API Docs中详细描述,先有文档后,然后再谈实现,研发内部,根据接口来定义各个模块的交互;测试的同学也可以根据接口来设计测试用例。


2. 尽可能保证接口幂等性,不论是读还是写。

读接口自然不需要多解释,大家都会做到。这里重点说两句,关于写接口的幂等性,分为同步写和异步写两种情况:

如果是同步写,直接使用乐观锁即可,通过使用使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。为数据增加一个版本标识,简单来说,就是更新数据前,先比较版本号,如果该版本号已经更新过了,就放弃更新,否则就直接更新。

对于异步写,本质上也一样,也是乐观锁的思路,可以数据上加上时间戳作为区分,值得注意的是,更新的内容用增量数据,而不要使用全量数据,避免请求时序错乱导致的错误。


   3. 接口可以降级

        在特殊情况下,服务不能正常工作的时候(超时,网络异常,Crash。。等等),很多时候,接口严重超时返回,会严重拖慢整个系统,导致系统彻底瘫痪掉。对外暴露的接口需要有能力返回“默认值”,而不是直接返回错误。


   4. 接口需要向下兼容

       这个点,我相信做过接口开发的同学都深有体会,特别是移动产品时代,要用户端来配合接口底层的改动,是一件成本很高的事情,所以当底层数据结构发生变化,或者协议发生变化的时候,需要特别注意。比较好的一个实践经验是,所有的接口都必须要带上版本号,根据版本号,就可以做很多特殊处理。


5.接口要保证无状态

        在微服务体系下,每一个服务都部署了2台或者多台,每次调用是无法保证被调用的同个服务的某个实例。反过来说,只有接口具备无状态的保证,我们才能自如的横向扩展服务的实例。如果在特定业务下,确实想拥有状态,那只能按照状态分为多个接口。


6. 不要过度抽象接口

这一点就比较纠结的,但是也不能不抽象,否者接口数会暴增,所以我们才抽象合并,或者在设计的时候就将数据类型选择为抽象类。同时,在我们实战中,会发现一些抽象接口反而不好维护,这部分接口的数据类型单一,由于抽象多了一层数据类型转换和判断。所以,对于接口类型的抽象要基于业务的需要而定,真不要简单的一步到位。


最后,由于我们谈的是微服务下的接口,所以要多谈一句微服务,我的一个观点,就是微服务切忌过度拆分,维护成本会反弹。一个微服务的API范围,应该等于满足对应特定业务能力的需要。我们做微服务的价值,本质上是要让我们具备快速响应业务需求的能力,任何违背这一点的设计,都不会拿到我们想象中的效果。