事件驱动

异步通知、重试与退避

了解事件通知为什么会重复,以及接收、确认、退避和补偿的基本方法。

事件通知

异步通知是在事件发生后,由事件源向接收地址发送 HTTP 请求。它适合传递“状态已经变化”这一事实,但不应被理解为只会发送一次或一定按顺序到达。

事件正文应包含事件编号、事件类型、发生时间、资源编号和必要状态。通知地址只负责接收,不应承载面向用户的页面内容。

接收流程

  1. 读取原始请求字节,限制正文大小。
  2. 验证时间戳、签名和事件类型。
  3. 使用事件编号执行幂等检查。
  4. 把事件写入本地队列或可靠存储。
  5. 尽快返回成功确认,由后台完成较慢处理。

把耗时任务放在确认响应之前,会增加超时和重复投递概率。快速确认不代表忽略处理结果,而是先可靠接收,再异步执行。

重试策略

只有暂时性失败适合自动重试,例如连接超时、服务暂不可用或明确的限流响应。字段格式错误、签名无效和权限不足通常不能通过原样重试恢复。

每次重试应保持相同事件编号。接收方必须能够识别重复事件,并返回稳定结果。

情况建议
连接失败、超时、5xx有限次数重试,并逐步增加等待时间
429 或带 Retry-After尊重服务端给出的等待建议
400、签名无效停止原样重试,记录并检查数据
接收成功但内部处理失败使用本地队列或补偿任务继续处理

退避与抖动

指数退避会随着失败次数增加等待时间,抖动则在等待时间中加入随机量。两者结合可以避免大量任务在同一时刻再次请求。

delay = min(max_delay, base_delay × 2^attempt)
actual_delay = random(0, delay)

重试次数必须有上限,并设置总时间预算。无限重试会让已经出现压力的依赖承担更多流量。

补偿与查询

通知只是同步状态的一种方式。系统还应提供主动查询或定时核对路径,用于发现通知遗漏、接收端停机和长期未完成记录。

补偿任务要能从中断位置继续,记录最后处理游标,并对每条记录使用与在线接口相同的状态规则。修正过程也应留下审计日志。

参考资料