如何测试代理请求取消,避免遗留幽灵流量

互联网请求通道依次经过代理节点,其中一条已取消的数据流干净停止并释放共享容量

关闭浏览器标签页、中止 API 请求或取消采集任务,并不能自动证明所有层级的工作都停止了。客户端可能放弃读取响应,但代理仍在转发字节,目标端仍在生成大响应,重试队列又创建了替代请求,或者连接池一直占用并发直到超时。

这些隐藏行为会浪费代理流量、占用并发、干扰计费并造成重复采集。本指南为已获授权的 HTTP、HTTPS CONNECT、SOCKS 与浏览器代理工作流建立可控的取消测试。

先定义“已取消”的完整含义

有效的取消契约需要覆盖每一层:

层级预期结果
应用任务以明确的取消状态结束,不能记为成功
重试控制器除非策略明确允许,否则不创建替代尝试
客户端传输响应体停止,流或套接字得到释放
代理路线隧道或请求不再占用活动容量
受控目标生成或传输停止,或单独标记已经完成
计量已传输字节与请求数量可以解释和核对

不要只把“调用方很快返回”定义为成功。用户看到的操作已经结束,后台流量仍可能继续。

建立安全测试端点

使用你控制的目标端,并提供四种确定性端点:

  1. 按固定间隔输出编号数据块的慢响应;
  2. 延迟首字节的响应;
  3. 以低速读取的有界上传接收器;
  4. 用于取消后健康检查的小型正常响应。

每个请求使用合成测试标识。目标端只记录标识、时间戳、收发字节数、连接状态和结束原因。测试中不要包含代理凭证、Cookie、个人数据或真实客户 URL。

对直连与每种已授权代理路线运行同一组测试。直连只作为诊断对照,不能成为生产回退。

覆盖不同取消时点

取消行为会随时点变化,至少测试:

  • DNS 或代理连接建立完成前;
  • 代理认证或 CONNECT 协商期间;
  • 收到响应头后、正文开始前;
  • 流式下载中途;
  • 有界上传中途;
  • 在客户端并发队列等待期间;
  • 刚出现看似可重试错误时;
  • 应用关闭过程中。

每次只改变一个条件,否则超时、服务端关闭与用户取消会混在同一条证据里。

在两端采集证据

客户端记录:

test_id
route_class
cancel_requested_monotonic_ms
client_returned_monotonic_ms
bytes_sent_before_cancel
bytes_received_before_cancel
retry_count_after_cancel
active_connections_before_after
queued_requests_before_after
final_reason_code

受控目标端记录首个请求字节、首个响应字节、最后观察到的字节、断开或完成时间以及总字节数。使用测试标识对应两端事件。持续时间使用单调时钟,跨系统关联才使用同步 UTC。

除非确有必要、已获授权并妥善保护,否则不要默认抓包。多数验收测试可以使用应用、代理与测试端点计数器完成,避免收集无关内容。

测试下载取消

通过代理启动慢速分块响应。收到固定数量的数据块后,使用运行时支持的取消机制在应用层取消。除非测试进程退出场景,否则不要直接杀死整个进程。

逐项确认:

  1. 客户端报告取消,而不是把部分正文标记为成功;
  2. 解析器不会把不完整响应写入数据集;
  3. 受控目标端在约定清理窗口内观察到数据流结束;
  4. 代理活动请求或连接占用回到基线;
  5. 自动重试不会换一个出口 IP 重新开始;
  6. 已知正常路线上的小型后续请求可以成功。

可结合代理响应完整性测试,防止部分正文被误认为完整结果。

测试上传取消

上传带来另一类风险:客户端得知最终结果前,目标端可能已经接收部分甚至全部请求。应使用可丢弃的合成对象,并让目标端提供实际接收字节数。

在不同上传百分比取消。客户端必须返回取消或结果不确定,不能假设操作已经回滚。凡是存在副作用的操作,重试前应使用幂等键或目标端提供的状态查询。

不能因为代理连接关闭,就自动重复付款、表单提交或账号变更。传输结果不确定不等于业务操作失败。

验证重试确实被抑制

许多重试库会把取消误分类为超时、连接重置或普通网络错误,于是在用户要求停止后立即创建新请求。

为任务携带明确的取消原因。重试层必须先判断取消,再判断状态码或异常类型。断言显式用户取消或调度取消后,重试次数保持为零。如果关闭策略允许稍后恢复,应创建带新决策记录的新任务,而不是悄悄延续旧任务。

可以使用代理 429 与重试处理指南,区分允许的瞬时恢复、取消、限速和永久失败。

检查连接池行为

取消不一定要关闭整条连接。HTTP/2 和 HTTP/3 可以取消一个流,同时保留其他健康流。HTTP/1.1 客户端在无法安全排空正文时,可能必须关闭或丢弃连接。必须测试生产实际使用的运行时和协议。

每次取消后测量:

  • 活动与空闲连接数量;
  • 并发槽位重新可用的时间;
  • 连接是否返回池中;
  • 后续响应的帧边界是否正确;
  • 其他在途流是否受到影响;
  • 重复循环后的文件描述符与内存变化。

不适合复用的连接必须退出池。复用仍残留未读响应字节的套接字,可能把旧字节附到新请求上,造成下一条结果损坏。

预先定义验收阈值

测试前确定阈值。示例契约可以要求:

  • 应用在 250 毫秒内确认取消;
  • 取消时间戳之后不出现新重试;
  • 流式测试端点在 2 秒内观察到断开;
  • 活动并发在 3 秒内回到基线;
  • 写入的数据集中部分记录为零;
  • 日志中的凭证与正文泄漏为零;
  • 后续对照请求成功;
  • 在服务说明的统计延迟内核对代理字节计数。

具体数值要符合运行时、地区和代理产品。目标是明确可重复的契约,而不是一味追求极小数字。

排错矩阵

现象优先排查方向
客户端返回后目标仍在发送传输中止传播与正文排空行为
取消后创建新请求重试分类与任务状态传播
并发长时间被占用连接池释放、隧道关闭与网关计量
下一响应混入异常字节不安全的 HTTP/1.1 连接复用
上传可能已经完成幂等机制与目标状态核对
只有一个市场清理失败地区网关、协议或网络中间层
直连能清理而代理不能代理隧道行为,而非仅应用取消

上线检查清单

  • 每个任务都有稳定的合成请求标识。
  • 取消与超时、失败、成功明确区分。
  • 重试逻辑先判断取消状态。
  • 部分下载绝不会作为完整数据入库。
  • 有副作用的上传使用幂等或状态核对。
  • 连接池计数会回到基线。
  • 不安全连接从复用池移除。
  • 必须使用代理时禁止直连回退。
  • 日志排除凭证、Cookie 和原始正文。
  • 服务商计量与客户端、测试端证据相互核对。
  • 按需要覆盖 IPv4、IPv6、HTTP 代理和 SOCKS 模式。
  • Global、北美、欧洲与 APAC 的结果分别审查。

常见问题

取消时应该关闭整条代理连接吗?

不一定。多路复用协议可以只取消一个流而不影响其他流。验收要求是已取消工作停止、资源释放且相邻请求不被破坏。

超时和取消相同吗?

不同。超时是等待过久后的策略决定,取消是用户、调度器或关闭流程发出的明确停止信号。两者可能产生相似传输错误,但重试策略不同。

换一个代理能解决取消卡住吗?

不能。轮换可能制造重复工作并掩盖清理缺陷。应先修复取消传播与资源计量。

已取消流量如何计费?

以服务商公开的计量定义为准。已经传输的字节仍可能计费。应核对客户端、代理与受控目标计数,而不是假设取消会抹去用量。

合规说明

取消测试只能针对你拥有或已获授权的目标与代理账号。使用合成内容、保守流量、明确清理窗口与最小化日志。不得通过取消和轮换请求规避限速、访问控制或发布者决定。