Bird 接受 SMS 之后、你的应用收到响应之前,连接可能会断开。用新的幂等键重试可能产生第二次发送,因为 Bird 会将其视为一个独立的请求。
幂等键如何工作?
你为每次预期的 SMS 发送设置一个 Idempotency-Key 请求头,并在重试相同请求时复用它。当 Bird 保留了原始响应后,匹配的重试会返回该响应而不会再次执行发送。
例如,一条订单确认消息在超时及重试过程中保持相同的幂等键。另一笔订单的确认消息则使用不同的幂等键。
重放的响应包含 Idempotency-Replay: true,你的日志可以据此区分重放与新处理的请求。
SMS 幂等键的作用域为你的工作区。Bird 按其幂等约定保留已完成的响应 三小时。超过该窗口后,同一幂等键可以执行新请求,因为其重放记录已过期。因此,一天后的重试需要先核实原始结果,再决定是否再次发送。
失败响应在告诉我什么?
错误码区分了三种情况:请求已变更、请求未完成和幂等保护不可用。
409且E01005 IdempotencyKeyReuse:同一幂等键被用于不同的请求。在重试之前先修正幂等键的分配,因为该幂等键属于原始请求。Bird 会比较方法、端点、路径与查询参数以及原始请求体。即使 JSON 中的空白字符变化也会使请求被视为不同。409且E01004 RequestInProgress:使用同一幂等键的并发请求尚未完成。短暂等待后使用相同的幂等键和请求重试,以便原始请求完成。进行中的锁会在 30 秒内过期。过期并不能确定原始发送是否已生效。503且E01033 IdempotencyUnavailable:执行前幂等保护不可用,因此本次尝试未执行。使用相同的幂等键和请求进行退避重试。此响应不能确定先前尝试的结果。- 其他
5xx响应或超时:使用相同的幂等键和请求进行退避重试。Bird 不会保留5xx响应。重试会重放已保留的成功响应,如果没有保留任何响应,则可能再次执行。
幂等请求头在这些重试中保持请求的身份不变。
幂等键能保证不出现重复吗?
幂等键能减少重复发送,但不能保证只执行一次。
发送可能在 Bird 保留响应之前就已生效。如果响应保留失败或进行中的锁过期,重试可能会再次执行发送。三小时的保留窗口同样限制了重放保护的范围。
保留你的应用事件和发送记录,以便在再次发送之前核实不确定的结果。在消息中包含订单号或参考编号,让收件人能够识别消息所对应的事件。
如果收件人手机上显示了两条相同的消息呢?
幂等键控制的是 API 的重试,而非收件人手机如何显示消息。仅凭截图无法确定重复消息的来源。
将完整的应用发送日志与 Bird 的消息记录进行比对。多个已接受的消息 ID 可以证明存在多次发送。在不完整的日志中只找到一个 ID 并不能证明重复发生在下游。联系支持团队排查时,请提供相关 ID、目标地址和时间戳。
我应该怎么做?
- 为每次预期的 SMS 发送 分配一个幂等键,并在重试时复用相同的请求。
- 对网络错误、超时和
5xx响应进行退避重试,保留幂等键以利用可用的重放保护。 - 修正请求变更冲突,并在原始请求仍在执行时延迟重试。
- 核实不确定的发送,包括超出三小时重放窗口的发送,然后再决定是否再次发送。
简而言之
一个幂等键标识一次预期的发送。
重试时复用相同的幂等键和请求。已保留的响应在三小时内可被重放。
409可以识别已变更或未完成的请求。IdempotencyKeyReuse 表示请求已变更。RequestInProgress 表示原始请求仍在执行,需要延迟重试。
幂等保护不可用,本次尝试被阻止。
503 IdempotencyUnavailable 响应表示本次尝试未执行,但不能确定先前尝试的结果。
响应重放降低了重复发送风险,但不能完全消除。
发送可能在响应被保留之前就已生效。过期的重放记录也会允许新的执行。