1. 接口参数校验
入参出参校验是每个程序员必备的基本素养。
你设计的接口,必须先校验参数。
比如入参是否允许为空,入参长度是否符合你的预期长度。
这个要养成习惯哈,日常开发中,很多低级bug都是不校验参数导致的。
比如你的数据库表字段设置为varchar(16),对方传了一个32位的字符串过来,如果你不校验参数,插入数据库直接异常了
出参也是,比如你定义的接口报文,参数是不为空的,但是你的接口返回参数,没有做校验,因为程序某些原因,只返回别人一个NULL值
2.修改老接口时,注意接口的兼容性
很多bug都是因为修改了对外旧接口,但是却不做兼容导致的。关键这个问题多数是比较严重的,可能直接导致系统发版失败的(接口兼容:解决思路之一加版本号
3.设计接口时,充分考虑接口的可扩展性
要根据实际业务场景设计接口,充分考虑接口的可扩展性
比如你接到一个需求时:是用户添加或者修改员工时,需要刷脸。那你是反手提供一个员工管理的提交刷脸信息接口?还是先思考:提交刷脸是不是通用流程呢?比如转账或者一键贴现需要接入刷脸的话,你是否需要重新实现一个接口呢?还是当前按业务类型划分模块,复用这个接口就好,保留接口的可扩展性。

4. 接口考虑是否需要防重处理
如果前端重复请求,你的逻辑如何处理?是不是考虑接口去重处理
当然,如果是查询类的请求,其实不用防重。如果是更新修改类的话,尤其金融转账类,就要过滤重复请求了。简单点,你可以使用Redis防重复请求,同样的请求方,一定时间间隔内的相同请求,考虑是否过滤。当然,转账类接口,并发不高的话,推荐使用数据库防重表,以唯一流水号作为主键或者唯一索引
5. 重点接口,考虑线程池隔离
一些登录,转账交易、下单等重要接口,考虑线程池隔离哈。如果你所有业务都共用一个线程池,有些业务出bug导致线程池阻塞打满的话,就寄,所有业务都影响了。
因此进行线程池隔离,重要业务分配多一点的核心线程,就更好地保护重要业务。
6. 调用第三方接口要考虑异常和超时处理
如果你调用第三方接口,或者分布式远程服务的话,需要考虑
- 异常处理:比如,你调别人的接口,如果异常了,怎么处理,是重试还是当作失败还是告警处理
- 接口超时:没法预估对方接口一般多久返回,一般设置个超时断开时间,以保护你的接口,之前见过一个生产问题,就是http调用不设置超时问题,最后响应方进程假死,请求一直占着线程不释放,拖垮线程池。
- 重试次数:你的接口调用失败,需不需要重试?重试几次?需要站在业务上角度思考这个问题
7. 接口实现考虑熔断和降级
当前互联网系统一般都是分布式部署的。而分布式系统中经常会出现某个基础服务不可用,最终导致整个系统不可用的情况,这种现象被称为服务雪崩效应。
为了应对服务雪崩,常见的做法是熔断和降级。最简单是加开关控制,当下游系统出问题时开关降级,不再调用下游系统。还可以选用开源组件Hystrix
8. 日志打印好,接口的关键代码,要有日志保驾护航
关键业务代码无论身处何地,都应该有足够的日志保驾护航。比如:你实现转账业务,转个几百万,然后转失败了,接着客户投诉,然后你还没有打印到日志。
9. 接口的功能定义要具备单一性
单一性是指接口做的事情比较单一、专一。比如一个登录接口,它做的事情就只是校验账户名密码,然后返回登录成功以及userid即可。
但是如果你为了减少接口交互,把一些注册、一些配置查询等全放到登录接口,就不太妥。
其实这也是微服务的一些思想,接口的功能单一、明确。比如订单服务、积分、商品信息相关的接口都是划分开的。将来拆分微服务的话,是不是就比较简便啦。
10. 接口合并或者说考虑批量处理思想
数据库操作或者是远程调用时,能批量操作就不要for循环调用
11. 接口实现过程中,恰当使用缓存
哪些场景适合使用缓存?读多写少且数据时效要求越低的场景。
缓存用得好,可以承载更多的请求,提升查询效率,减少数据库的压力。
比如一些平时变动很小或者说几乎不会变的商品信息,可以放到缓存,请求过来时,先查询缓存,如果没有再查数据库,并且把数据库的数据更新到缓存。
但是,使用缓存增加了需要考虑这些点:缓存和数据库一致性如何保证、集群、缓存击穿、缓存雪崩、缓存穿透等问题
12. 接口考虑热点数据隔离性
瞬时间的高并发,可能会打垮你的系统。
可以做一些热点数据的隔离。
比如业务隔离、系统隔离、用户隔离、数据隔离等
- 业务隔离:比如12306的分时段售票,将热点数据分散处理,降低系统负载压力
- 系统隔离:比如把系统分成了用户、商品、社区三个板块。这三个块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离
- 用户隔离:重点用户请求到配置更好的机器
- 数据隔离:使用单独的缓存集群或者数据库服务热点数据
13. 接口考虑幂等性
接口幂等实现方案主要有8种:
- select+insert+主键/唯一索引冲突
- 直接insert+主键/唯一索引冲突
- 状态机幂等
- 抽取防重表
- token令牌
- 悲观锁
- 乐观锁
- 分布式锁
14. 读写分离,优先考虑读从库,注意主从延迟问题
我们的数据库都是集群部署的,有主库也有从库,当前一般都是读写分离的。
比如你写入数据,肯定是写入主库,但是对于读取实时性要求不高的数据,则优先考虑读从库,因为可以分担主库的压力
如果读取从库的话,需要考虑主从延迟的问题
15. 接口注意返回的数据量,如果数据量大需要分页
一个接口返回报文,不应该包含过多的数据量。过多的数据量不仅处理复杂,并且数据量传输的压力也非常大,可以分页返回。
16. 好的接口实现,离不开SQL优化
我们做后端的,写好一个接口,离不开SQL优化
SQL优化从这几个维度思考:
- explain分析SQL查询计划(重点关注type、extra、filtered字段)
- show profile分析,了解SQL执行的线程的状态以及消耗的时间
- 索引优化(覆盖索引、最左前缀原则、隐式转换、order by以及group by的优化、join优化)
- 大分页问题优化(延迟关联、记录上一页最大ID)
- 数据量太大(分库分表、同步到es,用es查询)
17. 接口状态和错误需要统一明确
提供必要的接口调用状态信息。
比如你的一个转账接口调用是成功、失败、处理中还是受理成功等,需要明确告诉客户端。
如果接口失败,那么具体失败的原因是什么。
这些必要的信息都必须要告诉给客户端,因此需要定义明确的错误码和对应的描述。
同时尽量对报错信息封装一下,不要把后端的异常信息完全抛出给客户端
18. 你的接口,需要考虑限流
如果你的系统每秒抗住的请求是1000,如果一秒钟来了十万请求呢?换个角度就是说,高并发的时候,流量洪峰来了,超过系统的承载能力,怎么办呢?
如果不采取措施,所有的请求打过来,系统CPU、内存、Load负载飙得很高,最后请求处理不过来,所有请求无法正常响应。
针对这种场景,我们可以采用限流方案。就是为了保护系统,多余的请求,直接丢弃。
19. 保证接口正确性
保证接口正确性,换个角度讲,就是保证更少的bug,甚至是没有bug。
所以接口开发完后,一般需要开发自测一下。
然后的话,接口的正确还体现在,多线程并发的时候,保证数据的正确性等等