ADR 007: 弱网容错分析¶
状态¶
已接受 (2026-02-12)
背景¶
在 v3.0.4 版本中,对项目的弱网支持能力进行了全面分析,发现以下关键问题:
- 网络组件不统一:项目存在四套独立的网络请求实现(
FetchWorker、NetworkUtils、NetworkWorker、ComponentService),各自的超时/重试/退避策略不一致 NetworkWorker无超时机制:使用QEventLoop::exec()无限等待,弱网下可能永久阻塞线程FetchWorker超时不重试:超时是弱网最常见的错误类型,但FetchWorker在超时后直接放弃重试- 超时时间配置不合理:
FetchWorker的超时时间(8-10s)对弱网环境过短
分析结论¶
问题严重性分级¶
| 严重程度 | 问题 | 影响 |
|---|---|---|
| 严重 | NetworkWorker 无超时,永久阻塞 |
程序无响应 |
| 严重 | FetchWorker 超时不重试 |
弱网下批量导出全部失败 |
| 严重 | 超时时间过短(8-10s) | RTT > 2s 时首次连接大概率超时 |
| 中等 | 惊群效应 | 带宽竞争加剧 |
| 中等 | 线性退避(非指数退避) | 限流恢复慢 |
| 中等 | 固定 500ms 重试延迟 | 弱网下过于激进 |
| 低 | QNAM thread_local 泄漏 | 长期运行内存增长 |
各组件弱网能力对比¶
| 组件 | 超时 | 重试 | 退避策略 | 弱网评级 |
|---|---|---|---|---|
FetchWorker |
8-10s | 3次(超时不重试) | 线性 +1000ms | 差 |
NetworkUtils |
30s | 3次(超时可重试) | 递增 3/5/10s | 良好 |
NetworkWorker |
无 | 无 | 无 | 极差 |
ComponentService |
15s | 3次 | 递增 1/2/3s | 中等 |
决策¶
改进方向¶
基于分析结论,建议分两个优先级实施改进:
P0 改进(优先实施)¶
- 统一网络超时机制
- 为
NetworkWorker添加超时保护 -
评估是否将
NetworkWorker迁移至FetchWorker或NetworkUtils -
修复
FetchWorker超时重试逻辑 - 对
OperationCanceledError(超时)执行正常重试 -
与
NetworkUtils的超时重试行为保持一致 -
调整超时时间
- 组件信息:8s -> 15-20s
- 3D 模型:10s -> 30s
- 与
NetworkUtils的超时配置保持一致
P1 改进(后续实施)¶
- 统一退避策略
- 实现真正的指数退避(1s -> 2s -> 4s -> 8s)
-
加入随机抖动(Jitter)避免惊群效应
-
统一重试延迟
-
采用
NetworkUtils的递增延迟模式(3s -> 5s -> 10s) -
修复 QNAM 内存管理
- 使用
std::unique_ptr管理thread_local对象
后果¶
正面¶
- 明确了项目弱网支持的现状和改进方向
- 为后续版本的网络容错改进提供了清晰的优先级指导
- 统一各组件的网络策略标准
负面¶
- 改进工作需要投入额外的开发和测试时间
- 增加超时时间可能导致正常网络下的等待时间略有增加(可通过动态超时策略缓解)
风险¶
NetworkWorker的改动需要确认其是否仍被活跃使用,避免不必要的修改- 超时时间调整需要在弱网容错和用户体验之间取得平衡