如何写好对外的API微服务
写好对外API和对内API本质上是一样的,都需要考虑这几个方面?
- API文档;
- API安全性;
- API日志;
- API性能。
一、API文档
好的API文档,能够降低低效沟通带来的时间、人力成本。好的文档应具有的特性有:结构清晰、内容简洁易懂等。
好的API文档应该要有这些内容?
1.概述
(1)编制目的
(2)协议描述
a.应用名称
b.交互协议(通常HTTP)
c.请求数据格式
d.数据编码方式
e.字符编码方式
f.API地址
g.交互超时
2.接口列表
(1)具体接口名称
(2)接口描述
(3)请求频率
(4)请求URL
(5)请求参数
(6)请求参数描述
(7)响应结果
3.附录
(1)响应码对照
(2)其它补充
业内参考对象
可以借鉴参考,不一定照搬照抄,适合自己的才最重要。下面的具体实例和我上面列举的大同小异。
1.支付宝
支付宝支付api文档地址:
https://opendocs.alipay.com/apis/api_1
2.微信支付
微信支付api文档地址:
https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
3.聚合
聚合API文档:
https://www.juhe.cn/docs
例如身份证实名认证api文档地址:
https://www.juhe.cn/docs/api/id/103
4.腾讯云
腾讯云API文档:
https://cloud.tencent.com/document/api/
5.阿里云
阿里云API文档:
https://developer.aliyun.com/api
二、API安全性
API安全性的目的是防止被人攻击以及非法利用获取数据等。这就显得API安全性至关重要。常用API安全性设计有如下:
- token鉴权机制;
- 时间戳超时机制;
- API签名机制。
这三种机制我都经历过,其中token鉴权机制,我就主导过两次,一次是在创业公司,另一次是在目前这家公司。API签名机制前创业公司由我们组长主导,当时她的设计是时间戳+签名两者都结合起来,而后到了教育项目的时候由我这边开始结合shiro+jwt实现token鉴权机制。
关于Shiro+JWT+Token鉴权可以参考我写的这篇文章:
SpringBoot集成Shiro
关于SpringCloud之Security(本质上还是token鉴权,基于OAuth1.0),可以参考我写的这篇文章:
SpringCloud之Security
不仅仅是对外的API需要特别注重安全性,对内的API(本质上是自己的App和后台API交互)也一样,不然的话很容易受到如下攻击:
- DOS攻击;
- DDOS攻击。
当然了除了Token鉴权机制、时间戳机制、签名机制外,也可以自建一套独特的机制,例如最近做的对外API,我就结合了公私钥+签名机制做了鉴权,感兴趣的朋友可以参考这篇文档:
WebService安全机制的思考与实践
当然了,还有我曾经最早做的Blog系统,用一个中间表做session存储,每次登录会将用户唯一标识+sessionid插入这张表里,同时这张表会有一个创建时间,系统定时任务每分钟会执行一次,检测sessionid从创建到现在有没有超过8个小时,如果超过了会自动清除这条数据,每次登录会判断是否存在这条数据,如果存在则更新,不存在则新增。这样做的话有一个弊端就是正在操作的时候突然一下就被弹出去了,为此还要有一个接口实时请求刷新这张表,但频繁的操作数据表特别是用户量很大的时候并不是一个明智的选择,于是我让Redis来做这件事情。
三、API日志
API日志分为两个方面,以最近的实践经验,第一针对接口请求进行入日志表存储,第二针对请求的数据进行存入特定的xxx.log(也就是日志文件)。这样做的话主要的目的是针对对方推送调用API,而我方通过获取对方推送的数据进行处理和入库。而我方通常响应的结果不会是数据,只会是状态码便可以结合这两种方式进行处理。
但如果是我方既接收和处理数据,同时也接收和响应数据,那么就需要充分的考虑业务场景了,针对响应的结果是否有必要进行存储,在我看来有必要,特别是我方将数据卖给第三方,有证可查,避免少数客户的***难。
结合我最近的实践经验来看,我上面这样做虽然做到有据可查,但是也会存在一些问题的:
- 服务器的磁盘空间;
- MySQL单表容量2GB或500万行(如果超过这个数会影响性能)。
存在的问题也有办法解决:
- 针对服务器的磁盘空间,可以写shell脚本定期备份和清理;
- 对于MySQL可以采用分库分表的形式(有现成的解决方案,如MyCat、Sharding-JDBC等)。
四、API性能
API性能衡量指标主要如下:
- 响应时间;
- 请求成功率;
- TPS;
- 资源利用率;
- 数据库死锁;
- CPU限制;
- 内存。
最直接的衡量标准就是,哪怕我用户量多么大,API都能正常给我吐出我想要的结果而不是404或502,再或没有响应处于卡顿的状态。
API性能的好坏跟开发人员写的代码也有很大的关系,例如我最近一个同事,优化某个代码,将原本需要6~8个小时才能拿到结果优化到2个小时,最后由两个小时优化到几分钟。
这段代码我没细看过,听她跟我说,关键原因是:for循环里进行频繁的DB操作。
以我上家教育公司为例,面对庞大的用户所产生庞大的数据量,最常见的做法就是加服务器、加内存、加CPU等,通过服务器冗余来保持稳定性。
五、总结
不断回顾以往实践经历(做的好的+设计不足遇到的坑+未知的坑等),是为了让未来走的更稳。以前很少去复盘,导致不断犯一些重复性的错误,这些重复性错误,虽然能短时间解决,但在我看来是完全没有必要的,因为浪费了时间,这些时间原本可以做一些其它的事情(优化某段问题代码、重构一些冗余代码、学习一些新技术、夯实基础、学一些新东西(非技术类的)等)。