“该不该重试”不只是一个次数问题,更是“重试什么”的问题:重试 404 是浪费,不重试 503 是遗憾。这篇构造 1000 个行为固定的 URL(瞬时故障和永久错误混合),在同一个本机服务器上比较五种重试策略的成功数和浪费的请求。
每个 URL 最多尝试 3 次,重试间隔 0.01 秒,请求超时 0.2 秒,32 个线程 策略 最终成功 服务器收到 其中浪费在永久错误上 耗时 不重试 400 1000 0 0.7 秒 任何失败都重试 750 1950 500 1.1 秒 只重试网络错误(异常) 550 1150 0 0.7 秒 网络错误 + 所有 5xx 700 1550 200 0.9 秒 网络错误 + 408/425/429 + 502/503/504 750 1450 0 0.9 秒
不重试:400 个成功。只重试网络错误(超时、连接重置):550 个,漏掉了 5xx 和 429 的瞬时故障。网络错误加所有 5xx:700 个,但把永远 500 的页面也重试了 2 次(浪费 200 个请求)。任何失败都重试:750 个成功,但 1950 个请求里 500 个是浪费在 404/403/500 上的。白名单(网络错误、408/425/429、502/503/504):750 个成功,浪费为 0。
不重试:p403 50, p404 100, p500 100, t429 50, t502 50, t503 100, treset 100, ttimeout 50 任何失败都重试:p403 50, p404 100, p500 100 只重试网络错误(异常):p403 50, p404 100, p500 100, t429 50, t502 50, t503 100 网络错误 + 所有 5xx:p403 50, p404 100, p500 100, t429 50 网络错误 + 408/425/429 + 502/503/504:p403 50, p404 100, p500 100
最后只剩永久错误(403、404、永远 500)没成功,这些重试多少次都不会成功。把状态码按“可能瞬时”和“基本永久”分类,就是为了不去重试后者。
连续请求 3 次 /t503/1:[503, 200, 200] 连续请求 3 次 /p500/1:[500, 500, 500]
永远 500 的页面和只失败一次的 503,第一次响应看起来一样,500 通常是服务器自己的 bug,但有时也是暂时的。重试它们就必须接受一定浪费,所以要限制次数(这里是 3 次)。