技术解析 · 附来源的解答
指数退避重试
指数退避重试是一种错误处理策略:对失败操作进行连续重试时,每次重试之间的间隔呈指数增长。系统不是按固定间隔重试,而是在每次失败后等待更长时间,让收件服务器有时间从拥塞或暂时故障中恢复。
工作机制
流程从一个初始等待时间开始,例如 1 秒。如果第一次重试失败,等待时间会乘以一个常数因子,通常为 2。第二次重试在 2 秒后进行,第三次在 4 秒后,第四次在 8 秒后,依此类推。这种几何级数增长会一直持续,直到达到最大延迟阈值或最大尝试次数,此时邮件会被标记为永久性失败。
对发件人的重要性
这种方法可以防止发件人无意中对收件邮件服务器发起拒绝服务攻击。如果数千封邮件同时失败,且全部每 10 秒重试一次,由此产生的流量峰值可能让收件方一直无法恢复。通过分散重试,发件人可以保持更好的信誉,并提高暂时性 4xx SMTP 错误在邮件被丢弃之前得到解决的可能性。
运维注意事项
这一策略的一个关键补充是抖动(jitter),即在延迟中加入少量随机噪声。没有抖动时,同时失败的多个请求会以同步的波次重试,形成流量尖峰。加入抖动可以确保重试在时间窗口内均匀分布,进一步减轻基础设施的压力。
常见实现错误
开发者经常忘记设置最大重试次数或延迟上限。没有上限时,等待时间可能增长到数小时甚至数天,给事务性邮件带来无法接受的延迟。另一个错误是把 5xx 永久性失败当作可重试错误;指数退避只应用于 4xx 暂时性错误,例如速率限制或临时灰名单。
具体示例
假设通过 API 发送一封事务性邮件。第 1 次尝试因 421 服务器繁忙错误而失败,系统等待 2 秒;第 2 次尝试失败,系统等待 4 秒;第 3 次尝试失败,系统等待 8 秒。到第 4 次尝试时,收件服务器很可能已经清空了队列,邮件得以被接收。SendHQ 在 https://sendhq.cc/tools 提供免费工具,帮助您提升邮件基础设施的管理效率。
团队常问的问题
固定退避和指数退避有什么区别?
固定退避无论失败多少次都每隔 X 秒重试一次。指数退避则在每次失败后延长间隔,以减轻目标服务器的负载。
什么时候应该停止重试?
当返回 5xx 永久性失败、达到最大尝试次数或触及最大延迟上限时,应停止重试。
抖动会影响指数增长吗?
不会。抖动只是在计算出的指数延迟上加一个随机偏移量,以防多个并发请求同步重试形成尖峰。
一手资料
- RFC 5321:简单邮件传输协议(SMTP) — RFC Editor
- M3AAWG 最佳通用实践 — M3AAWG