从我看到的很多文章和商业 API 中,大多数人通过要求客户端提供 requestId 或幂等 key (例如 https://www.masteringmodernpayments.com/blog/idempotent-stripe-requests)来使他们的 API 幂等,并且基本上将 requestId <-> 响应映射存储在贮存。因此,如果有请求传入,而该 map 中已经存在,应用程序将只返回存储的响应。
这对我来说很好,但我的问题是如何处理在第一个调用仍在进行时第二个调用进来的情况?
这是我的问题
我想理想的行为是第二个调用一直等待直到第一个调用完成并返回第一个调用的响应?人们是这样做的吗?
如果是,第二个调用应该等待第一个调用完成多长时间?
如果第二次调用有等待时间限制,而第一次调用仍未完成,它应该告诉客户端什么?它是否应该不返回任何响应,以便客户端超时并重试?
最佳答案
对于奇妙 list ,我们使用数据库约束来确保没有请求 ID(这是我们每个表中的一列)被使用两次。由于我们的数据库技术(postgres)保证不可能插入两条违反此约束的记录,因此我们只需要对潜在的插入错误做出适当的 react 即可。基本上,我们将此细节外包给我们的数据存储。
我会建议,无论您如何处理,都尽量不需要在您的应用程序中进行协调。如果您试图知道两件事是否同时发生,那么很可能会出现错误。相反,可能有一个您已经在使用的系统可以提供您需要的保证。
现在,具体解决您的三个问题:
- 对我们来说,因为我们使用数据库约束,所以数据库会处理让事情排队等待的事情。这就是为什么我个人更喜欢旧的 SQL 数据库——不是因为 SQL 或关系,而是因为它们非常擅长锁定和排队。我们将 SQL 数据库用作不连贯的哑表。
- 这在很大程度上取决于您的系统。我们尝试将每个系统和子系统中的所有超时调整为 1 秒左右。我们宁愿快速失败也不愿排队。您可以测量并查看第 99 个百分位数的时间,如果您无法提前知道,只需将其设置为超时即可。
- 我们将向客户端返回 504 http 状态(和适当的响应正文)。拥有幂等 key 的原因是客户端可以重试请求 - 所以我们从不担心超时并让他们这样做。同样,我们宁愿快速超时并解决问题,也不愿让事情排队。如果事情排成一排,那么即使在某些事情得到解决之后,也必须等待一段时间才能让事情变得更好。
关于api - 如何在同时接收具有相同 ID 的多个请求时保持 API 幂等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31621970/