《我实测了11个HTTP弹性库的21个场景,结果如何?》
标签:
#软件开发 #HttpResilience_对比测试_Retry_CircuitBreaker_Hedging_取消与超时正确性
总结:
作者在开发自己的 fetch 弹性封装库 ffetch 时发现了大量隐藏的正确性问题,于是搭建了一套覆盖 21 个场景的测试矩阵,对 11 个流行的 HTTP 弹性库(包括自己 ffetch 5.7.1)进行横向对比。结果显示:基础的"重试"行为在所有库中都表现良好,但 25 个失败几乎全部集中在组合场景——取消发生在退避等待中、超时与重试叠加、队列中的请求被取消、熔断器半开状态下迟到响应等。作者也坦承测试套件源自自己修过的 bug,存在确认偏差,且部分判定标准(如取消后必须立即停止派发)严于官方文档。矩阵每周自动重建并公开于 fetchkit.org/http-resilience。
文章要点:
1. 测试方法很扎实:21 个场景覆盖重试、超时、熔断、舱壁、对冲、请求去重,用脚本化 fetch + Vitest 假定时器精确控制中止时刻,jitter 固定 random=0.5,并附 2 个真实 node:http 集成场景。
2. 全部 11 个库都通关的"共同强项"是基础重试类场景:重试恢复、重试耗尽、零重试、真实 HTTP 重试、请求体字节级回放,共 55/147 个实现单元。
3. 失败高度聚类于"组合场景":典型如"重试 + 退避中取消",fetch-retry、ofetch、wretch、resilient-fetch-client、fetch-resilience、@resili/fetch 六库会延迟结算甚至取消后继续派发请求;fetch-retry 的源码问题暴露——退避用的是裸
4. 舱壁队列几乎全军覆没:五家有队列的库中四家在"排队请求被取消"场景全挂——取消的调用方仍占着坑位不放,替换请求被拒,个别还照样派发了已取消的请求,ffetch 是唯一通过者。
5. 重试 + 整体超时、Retry-After + 取消、hooks 抛错等场景暴露多家库"超时只罩单次尝试不罩重试循环"、回调拒绝后调用方永久挂起等问题,wretch 甚至会变成一个永远 await 的悬空 Promise。
6. 对冲(hedging)是最不成熟的表面:仅三个库提供带可配置启动延迟的对冲;flowshield 在所有超时设置下都失败,超时后仍启动对冲分支且分支不收手,等于白发给服务器一个没人等的请求。
7. 熔断器组合场景里作者自己的 ffetch 也栽了:半开状态下迟到成功响应会错误清除新开启状态(缺代次计数器);fetch-smartly 和 ts-retry-circuit 更严重,新冷却期被误清导致下一个请求吃掉本应给健康调用方的恢复响应。
8. 作者最后强调方法论局限:无性能基准、无 API 设计评价,场景源于自己修过的 bug 存在确认偏差;建议读者不要只看"功能有没有",而要按自己应用的真实组合方式去测。
URL:
https://blog.gaborkoos.com/posts/2026-10-04-I-Tested-11-Http-Resilience-Libraries/
标签:
#软件开发 #HttpResilience_对比测试_Retry_CircuitBreaker_Hedging_取消与超时正确性
总结:
作者在开发自己的 fetch 弹性封装库 ffetch 时发现了大量隐藏的正确性问题,于是搭建了一套覆盖 21 个场景的测试矩阵,对 11 个流行的 HTTP 弹性库(包括自己 ffetch 5.7.1)进行横向对比。结果显示:基础的"重试"行为在所有库中都表现良好,但 25 个失败几乎全部集中在组合场景——取消发生在退避等待中、超时与重试叠加、队列中的请求被取消、熔断器半开状态下迟到响应等。作者也坦承测试套件源自自己修过的 bug,存在确认偏差,且部分判定标准(如取消后必须立即停止派发)严于官方文档。矩阵每周自动重建并公开于 fetchkit.org/http-resilience。
文章要点:
1. 测试方法很扎实:21 个场景覆盖重试、超时、熔断、舱壁、对冲、请求去重,用脚本化 fetch + Vitest 假定时器精确控制中止时刻,jitter 固定 random=0.5,并附 2 个真实 node:http 集成场景。
2. 全部 11 个库都通关的"共同强项"是基础重试类场景:重试恢复、重试耗尽、零重试、真实 HTTP 重试、请求体字节级回放,共 55/147 个实现单元。
3. 失败高度聚类于"组合场景":典型如"重试 + 退避中取消",fetch-retry、ofetch、wretch、resilient-fetch-client、fetch-resilience、@resili/fetch 六库会延迟结算甚至取消后继续派发请求;fetch-retry 的源码问题暴露——退避用的是裸
setTimeout,从不读 init.signal。4. 舱壁队列几乎全军覆没:五家有队列的库中四家在"排队请求被取消"场景全挂——取消的调用方仍占着坑位不放,替换请求被拒,个别还照样派发了已取消的请求,ffetch 是唯一通过者。
5. 重试 + 整体超时、Retry-After + 取消、hooks 抛错等场景暴露多家库"超时只罩单次尝试不罩重试循环"、回调拒绝后调用方永久挂起等问题,wretch 甚至会变成一个永远 await 的悬空 Promise。
6. 对冲(hedging)是最不成熟的表面:仅三个库提供带可配置启动延迟的对冲;flowshield 在所有超时设置下都失败,超时后仍启动对冲分支且分支不收手,等于白发给服务器一个没人等的请求。
7. 熔断器组合场景里作者自己的 ffetch 也栽了:半开状态下迟到成功响应会错误清除新开启状态(缺代次计数器);fetch-smartly 和 ts-retry-circuit 更严重,新冷却期被误清导致下一个请求吃掉本应给健康调用方的恢复响应。
8. 作者最后强调方法论局限:无性能基准、无 API 设计评价,场景源于自己修过的 bug 存在确认偏差;建议读者不要只看"功能有没有",而要按自己应用的真实组合方式去测。
URL:
https://blog.gaborkoos.com/posts/2026-10-04-I-Tested-11-Http-Resilience-Libraries/