事件驱动
异步通知、重试与退避
了解事件通知为什么会重复,以及接收、确认、退避和补偿的基本方法。
事件通知
异步通知是在事件发生后,由事件源向接收地址发送 HTTP 请求。它适合传递“状态已经变化”这一事实,但不应被理解为只会发送一次或一定按顺序到达。
事件正文应包含事件编号、事件类型、发生时间、资源编号和必要状态。通知地址只负责接收,不应承载面向用户的页面内容。
接收流程
- 读取原始请求字节,限制正文大小。
- 验证时间戳、签名和事件类型。
- 使用事件编号执行幂等检查。
- 把事件写入本地队列或可靠存储。
- 尽快返回成功确认,由后台完成较慢处理。
把耗时任务放在确认响应之前,会增加超时和重复投递概率。快速确认不代表忽略处理结果,而是先可靠接收,再异步执行。
重试策略
只有暂时性失败适合自动重试,例如连接超时、服务暂不可用或明确的限流响应。字段格式错误、签名无效和权限不足通常不能通过原样重试恢复。
每次重试应保持相同事件编号。接收方必须能够识别重复事件,并返回稳定结果。
| 情况 | 建议 |
|---|---|
| 连接失败、超时、5xx | 有限次数重试,并逐步增加等待时间 |
| 429 或带 Retry-After | 尊重服务端给出的等待建议 |
| 400、签名无效 | 停止原样重试,记录并检查数据 |
| 接收成功但内部处理失败 | 使用本地队列或补偿任务继续处理 |
退避与抖动
指数退避会随着失败次数增加等待时间,抖动则在等待时间中加入随机量。两者结合可以避免大量任务在同一时刻再次请求。
delay = min(max_delay, base_delay × 2^attempt)
actual_delay = random(0, delay)
重试次数必须有上限,并设置总时间预算。无限重试会让已经出现压力的依赖承担更多流量。
补偿与查询
通知只是同步状态的一种方式。系统还应提供主动查询或定时核对路径,用于发现通知遗漏、接收端停机和长期未完成记录。
补偿任务要能从中断位置继续,记录最后处理游标,并对每条记录使用与在线接口相同的状态规则。修正过程也应留下审计日志。