Files
waf-platform/EdgeHttpDNS/sdk/ios/AlicloudHttpDNSTests/Network/TIMEOUT_ANALYSIS.md
2026-02-20 17:56:24 +08:00

6.0 KiB
Raw Blame History

超时对连接复用的影响分析

问题描述

当前测试套件没有充分验证超时与连接池交互的"无形结果"intangible outcomes可能存在以下风险

  • 超时后的连接泄漏
  • 连接池被超时连接污染
  • 连接池无法从超时中恢复
  • 并发场景下部分超时影响整体池健康

代码行为分析

超时处理流程

HttpdnsNWHTTPClient.m:144-145

if (!rawResponse) {
    [self returnConnection:connection forKey:poolKey shouldClose:YES];
    // 返回 nilerror 设置
}

returnConnection:forKey:shouldClose: (line 279-281)

if (shouldClose || connection.isInvalidated) {
    [connection invalidate];    // 取消底层 nw_connection
    [pool removeObject:connection];  // 从池中移除
}

结论:代码逻辑正确,超时连接会被移除而非留在池中。


当前测试覆盖情况

已有测试:testIntegration_RequestTimeout_ReturnsError

验证内容:

  • 超时返回 nil response
  • 超时设置 error

未验证内容(缺失):

  • 连接是否从池中移除
  • 池计数是否正确
  • 后续请求是否正常工作
  • 是否存在连接泄漏
  • 并发场景下部分超时的影响

需要验证的"无形结果"

1. 单次超时后的池清理

场景

  1. 请求 A 超时timeout=1s, endpoint=/delay/10
  2. 验证池状态

应验证:

  • Pool count = 0连接已移除
  • Total connection count 没有异常增长
  • 无连接泄漏

测试方法

[client resetPoolStatistics];

// 发起超时请求
NSError *error = nil;
HttpdnsNWHTTPClientResponse *response = [client performRequestWithURLString:@"http://127.0.0.1:11080/delay/10"
                                                                   userAgent:@"TimeoutTest"
                                                                     timeout:1.0
                                                                       error:&error];

XCTAssertNil(response);
XCTAssertNotNil(error);

// 验证池状态
NSString *poolKey = @"127.0.0.1:11080:tcp";
XCTAssertEqual([client connectionPoolCountForKey:poolKey], 0, @"Timed-out connection should be removed");
XCTAssertEqual([client totalConnectionCount], 0, @"No connections should remain");
XCTAssertEqual(client.connectionCreationCount, 1, @"Should have created 1 connection");
XCTAssertEqual(client.connectionReuseCount, 0, @"No reuse for timed-out connection");

2. 超时后的池恢复能力

场景

  1. 请求 A 超时
  2. 请求 B 正常(验证池恢复)
  3. 请求 C 复用 B 的连接

应验证:

  • 请求 B 成功(池已恢复)
  • 请求 C 复用连接connectionReuseCount = 1
  • Pool count = 1只有 B/C 的连接)

3. 并发场景:部分超时不影响成功请求

场景

  1. 并发发起 10 个请求
  2. 5 个正常timeout=15s
  3. 5 个超时timeout=0.5s, endpoint=/delay/10

应验证:

  • 5 个正常请求成功
  • 5 个超时请求失败
  • Pool count ≤ 5只保留成功的连接
  • Total connection count ≤ 5无泄漏
  • connectionCreationCount ≤ 10合理范围
  • 成功的请求可以复用连接

4. 连续超时不导致资源泄漏

场景

  1. 连续 20 次超时请求
  2. 验证连接池没有累积"僵尸连接"

应验证:

  • Pool count = 0
  • Total connection count = 0
  • connectionCreationCount = 20每次都创建新连接因为超时的被移除
  • connectionReuseCount = 0超时连接不可复用
  • 无内存泄漏(虽然代码层面无法直接测试)

5. 超时不阻塞连接池

场景

  1. 请求 A 超时endpoint=/delay/10, timeout=1s
  2. 同时请求 B 正常endpoint=/get, timeout=15s

应验证:

  • 请求 A 和 B 并发执行(不互相阻塞)
  • 请求 B 成功(不受 A 超时影响)
  • 请求 A 的超时连接被正确移除
  • Pool 中只有请求 B 的连接

6. 多端口场景下的超时隔离

场景

  1. 端口 11443 请求超时
  2. 端口 11444 请求正常
  3. 验证端口间隔离

应验证:

  • 端口 11443 pool count = 0
  • 端口 11444 pool count = 1
  • 两个端口的连接池互不影响

测试实现建议

P 组:超时与连接池交互测试

P.1 单次超时清理验证

  • testTimeout_SingleRequest_ConnectionRemovedFromPool

P.2 超时后池恢复

  • testTimeout_PoolRecovery_SubsequentRequestSucceeds

P.3 并发部分超时

  • testTimeout_ConcurrentPartialTimeout_SuccessfulRequestsReuse

P.4 连续超时无泄漏

  • testTimeout_ConsecutiveTimeouts_NoConnectionLeak

P.5 超时不阻塞池

  • testTimeout_NonBlocking_ConcurrentNormalRequestSucceeds

P.6 多端口超时隔离

  • testTimeout_MultiPort_IsolatedPoolCleaning

Mock Server 支持

需要添加可配置延迟的 endpoint

  • /delay/10 - 延迟 10 秒(已有)
  • 测试时设置短 timeout如 0.5s-2s触发超时

预期测试结果

验证项 当前状态 目标状态
超时连接移除 未验证 验证池计数=0
池恢复能力 未验证 后续请求成功
并发超时隔离 未验证 成功请求不受影响
无连接泄漏 未验证 总连接数稳定
超时不阻塞 未验证 并发执行不阻塞
多端口隔离 未验证 端口间独立清理

风险评估

如果不测试这些场景的风险:

  1. 连接泄漏:超时连接可能未正确清理,导致内存泄漏
  2. 池污染:超时连接留在池中,被后续请求复用导致失败
  3. 级联故障:部分超时影响整体连接池健康
  4. 资源耗尽:连续超时累积连接,最终耗尽系统资源

当前代码逻辑正确性: 高(代码分析显示正确处理) 测试验证覆盖率: 低(缺少池交互验证)

建议: 添加 P 组测试以提供可观测的证据证明超时处理正确。


创建时间: 2025-11-01 维护者: Claude Code