说一说API接口设计应该注意哪些事项

2023-01-08  本文已影响0人  天草二十六_简村人

一、背景

API接口设计在微服务开发的过程中太重要了,一旦发布出去了,客户端也好,调用方也好,再想让他们升级或者改动的难度非常大。
这要求我们在定义接口的时候,需要慎之又慎,不可马虎。

二、目标

二、设计思路

1、可扩展性

后期迭代的过程中,难免会增加一些参数,当然得是非必填的,否则之前的调用就会报错。

// 反例
// 删除题目
@DeleteMapping("/api/v1/answerRoom/{answerRoomId}/stu/{stuId}/task/{taskId}/topic/{topicId}")

在path中带入了太多的PathVariable参数,意味着他们是必填的,不仅导致路径太长,而且破坏了可扩展性。

// 正例
// 删除题目,它的目标对象是题目ID,不跟其他无关的领域做强耦合。
@DeleteMapping("/api/v1/topic/{topicId}")

你可能会反问说,题目一定和它的上级领域相关的啊,离不开任务或答疑室,也离不可题目所属的学生ID。所以上面的接口设计,也是正确的啊。
接口设计没有对错之分,只有原则的把握度的问题。熟好熟劣,自己推敲再三。

2、单一职责

有时候接口需要拆分为多个接口,有时候又可能需要合并抽象为一个接口。

2.1、商品的相关接口

上下架、修改库存等从商品的编辑接口抽离出来。

image.png

2.2、积分的发放

用户获得积分的途径有多种,拆分为用户购买积分、奖励发放积分和管理后台手动发放给用户等。

2.3、聚合支付

支付平台需要将多种支付渠道(微信支付、支付宝支付和不同的银行渠道)的支付请求,合并为一个抽象接口。而不是微信支付一个接口、支付宝支付又是另一个接口,以支付渠道为维度的话,虽然隔离性是好,但是业务对接方要吐槽不停。
支付平台还需要将多个对接的业务方,也合并为一个接口。
总之,对外的支付请求接口,就一个聚合接口。

3、隔离性

保证接口的粒度尽可能小,比如和支付方对接,我们都需要提供回调接口给到第三方支付。这时候,和上面的支付请求接口相反,往往是按支付渠道拆分为多个回调接口。

image.png
@PostMapping("/api/v1/notify/abc")
@PostMapping("/api/v1/notify/alipay")
@PostMapping("/api/v1/notify/hzbank")
@PostMapping("/api/v1/notify/icbc")
@PostMapping("/api/v1/notify/wxpay")

当然,入口拆分开来,是因为他们回调的参数体差异很大,所以我们需要把共性的处理逻辑,放在一个抽象类里,实现代码的复用。

4、幂等性

我们说一个接口做到了幂等,必须满足可以重试(不建议给调用方直接报错提示)

实现幂等的方式有很多,一般在post请求体中增加一个token字段 。接口在处理业务逻辑前锁定这个token对象即可。可以把token入库,处理完业务,再删除token。 当然也可以不删除token,这将视你怎么使用了。

5、接口的并发

在对接口的性能摸底的时候,期望的响应时间内,当时的qps并发量为多少。

常见的实现方式有:

一般建议你使用基于版本号的乐观锁,因为它的粒度最小,易于控制。

这里举一个分布式锁的例子,支付系统的回调接口是对外暴露出去的,防止被人攻击,或者第三方支付的频繁回调,我们往往是会对支付流水号进行一个锁定。好处是可以利用支付订单的状态机机制,避免重复处理支付回调。(如果是已支付,则返回)而因为在分布式的场景下,支付网关是有多个节点,想要锁定支付流水号,必须是使用分布式锁了。

6、一致性

这里的一致性,是说一个接口方法的所有操作而言。如果全部是操作事务性的数据库,则可以利用数据库的事务来保证。如果还涉及调用外部服务的接口,则需要通过补偿机制和持久化的重试来做到尽可能的一致性。

不太建议你引入分布式事务框架来做,更多地倾向于本地日志表。

这里不会详细讲解上述,只是给你一个提醒,设计和实现接口的时候,有没有满足一致性的要求。

上文不满足事务数据库的事务机制的情况,除了典型的微服务之间的接口调用外,还有redis、rabbitmq等中间件的操作,也是无法支持事务。

当然,后者想要满足接口的一致性,就显得更加困难了。这里推荐你对重要业务,做到必要的补偿。

使用xxl-job分布式的定时任务,对可能出错的业务做补偿,也可用来和业务对接方做定期的对账。

四、和接口设计的其他思路

将查询类的接口和操作类的接口,区分开来。操作类的接口,一般复杂在处理的表及字段比较多,但是它的qps比较低。查询类的接口,它是复杂在拼接数据,所以我们建议是做数据异构,查询异构后的数据。

1、分库分表

提高写入的qps,结合接口的qps来具体确定是否引入分库分表方案。

2、读写分离

上一篇 下一篇

猜你喜欢

热点阅读