代理 IP 并发数指某一时刻仍在发送、等待或接收响应的代理请求数量。它不等于线程数、不等于代理 IP 数量,也不等于每秒完成的请求数。用于初步估算时,可以采用:理论在途并发 ≈ 稳定成功 QPS × 平均端到端响应时间(秒)。真正上线前,还要用自己的目标地址、地区和请求内容做阶梯测试。

例如,一个合规数据任务希望稳定完成 30 个请求/秒,实测平均端到端响应时间为 0.8 秒,那么理论在途并发约为 24;如果响应时间升到 2 秒,即使目标成功 QPS 不变,也需要约 60 个并发。并发不是越大越好:超过链路或目标服务的承受点后,常见结果是延迟上升、超时和重试增加,实际成功吞吐反而下降。

文章目录

  1. 代理数量、线程、连接、并发与 QPS
  2. 代理 IP 并发数的估算公式
  3. 并发、QPS 与带宽的关系
  4. 单个代理 IP 的并发边界
  5. 阶梯测试与记录方法
  6. 常见瓶颈与错误信号
  7. 测出瓶颈后,应该扩什么资源
  8. 常见问题

一、代理数量、线程、连接、并发与 QPS

很多容量估算出错,不是公式不会算,而是一开始把不同指标当成了同一件事。一个脚本可以启动 100 个线程,但其中一部分可能在等待任务;一个浏览器页面也可能为了图片、字体和接口同时建立多条请求。反过来,启用连接复用后,多次请求又可能共用同一条 TCP 连接。

指标 实际含义 常见误解 应该怎样统计
代理 IP 数量 任务可使用的出口地址数量 一个 IP 就等于一个并发 记录实际出现过的出口 IP,并按会话或任务关联
线程或协程数 客户端安排任务的执行单元数量 开了 100 个线程,就一定有 100 个请求同时进行 从程序运行器或连接池配置中读取
并发请求数 同一时刻尚未完成的在途请求数量 并发越高,成功 QPS 一定越高 按请求开始与结束时间计算峰值和稳定区间
连接数 客户端、代理和目标之间建立的网络连接数量 一个请求始终对应一条新连接 结合客户端连接池、Keep-Alive 和系统连接状态观察
QPS / RPS 每秒完成的请求量;业务上更应关注成功请求量 只要提高线程数,QPS 就会按比例增加 用完成请求数除以稳定测试时长,并单列成功 QPS
带宽 单位时间能够传输的数据量 带宽足够就不会超时 同时记录上行、下行、峰值和持续吞吐

MDN 的 HTTP 连接管理说明指出,持久连接可以被多次请求复用,而且客户端到代理、代理到目标服务可能采用不同的连接方式。因此,“请求并发”和“TCP 连接数”通常有关联,但不能直接画等号。

代理IP数量线程连接数并发请求与QPS关系图
线程负责调度任务,并发表示正在进行的请求,连接承载请求,QPS反映单位时间完成量,IP数量则描述可使用的出口地址。

二、代理 IP 并发数的估算公式

在请求到达率和完成率相对稳定、系统没有明显排队积压时,可以用下面的关系做初步估算:

理论在途并发 ≈ 稳定成功 QPS × 平均端到端响应时间(秒)

稳定成功 QPS ≈ 理论在途并发 ÷ 平均端到端响应时间(秒)

AWS 关于并发计算的官方说明使用“平均每秒请求数 × 平均请求时长”估算同时在途的任务数量。套用到代理容量规划时,本文把 QPS 进一步限定为稳定完成且通过结果校验的请求率;响应时间则从客户端发起请求开始计算到完整接收结果为止,而不是只看代理节点的 Ping 值。

目标成功 QPS 平均响应时间 理论在途并发 解读
5 0.4 秒 约 2 先从低并发验证,不需要直接开大量线程
20 0.8 秒 约 16 适合从 10、15、20 逐级观察稳定点
20 2 秒 约 40 目标速度不变,但响应变慢会占用更多并发槽位
50 1.5 秒 约 75 应同步核查客户端、带宽、代理和目标服务限制

上表是计算示例,不是任何套餐的性能承诺。平均值适合估算理论关系,p95 延迟更适合观察慢请求是否开始堆积。若平均响应时间看起来正常,但 p95 已明显上升,就不宜仅凭平均值继续提高并发。

代理并发数根据目标QPS与响应时间计算流程图
先确定业务需要的成功QPS,再测端到端响应时间,得到理论并发后通过阶梯测试寻找可持续运行区间。

三、并发、QPS 与带宽的关系

并发解决的是“同时有多少请求在路上”,带宽解决的是“这些请求每秒要传多少数据”。文本接口响应很小,几十个并发也可能占用不了多少带宽;图片、文件或完整网页响应较大,即使 QPS 不高,也可能先把链路推到瓶颈。

纯业务数据带宽(Mbps)≈ QPS × 单次请求平均总传输量(MB)× 8

假设一次请求的上行和下行合计约 1.5 MB,稳定完成 12 QPS,纯业务数据约为 144 Mbps。这个数字还没有计入协议开销、连接握手、重定向、重传和失败重试,不能直接当成采购带宽。浏览器页面还会加载图片、字体和接口请求,流量通常不只是一份 HTML;如果实际用量高于预期,可以继续查看代理流量消耗过快的排查方法

因此,估算时至少要同时保留四组数据:成功 QPS、平均与 p95 响应时间、单次请求平均传输量、测试期间峰值带宽。只记录“开了多少线程”,无法判断瓶颈发生在哪一层。

四、单个代理 IP 的并发边界

单个代理 IP 没有一个适用于所有业务的固定并发值。同一出口访问一个轻量接口和加载一个包含大量资源的网页,连接时长与数据量完全不同;同样是 20 并发,不同地区、目标地址和网络路径也可能得到不同结果。

真正限制成功吞吐的通常是以下几层中最先达到上限的一层:

  • 客户端:CPU、内存、线程池、连接池、文件描述符和本地网络;
  • 代理入口:账号、网关、端口、并行会话及服务约定;
  • 代理出口:出口 IP、服务器资源、线路带宽与地区质量;
  • 目标服务:接口容量、公开的速率限制和服务端响应时间;
  • 请求内容:返回体大小、重定向次数、TLS 建连与失败重试。

因此,不要根据代理 IP 数量直接分配线程。例如有 20 个出口 IP,并不表示“每个 IP 开 10 线程,总并发一定是 200”。应该先按目标服务允许的访问规则设定总体请求节奏,再观察不同出口、不同连接池之间的成功率和延迟。

五、阶梯测试与记录方法

容量测试只应针对自有系统、测试环境或已经获得授权的目标地址进行。不要用公开第三方接口做高并发压测,也不要为了绕过对方限速而更换 IP。一个更可靠的过程,是先固定请求内容和地区,再逐级增加并发。

  1. 建立单请求基线:用并发 1 测出正常响应时间、状态码和返回内容;
  2. 设置阶梯:可以从 1、5、10、20 开始,每一级运行到数据进入稳定区间;
  3. 固定变量:同一轮不要同时更换地区、目标地址、请求内容和代理类型;
  4. 记录结果:统计总 QPS、成功 QPS、成功率、平均延迟、p95、错误码、超时和传输量;
  5. 找到拐点:当并发继续增加但成功 QPS 不再提高,或者 p95 与错误率明显恶化,就回退到前一个稳定档位;
  6. 分目标复测:不同地区和目标服务分别建档,不把某个地址的结果套用到所有任务。

Grafana k6 的指标文档建议从请求量、错误率和请求时长三个方向观察性能。对于代理测试,还应再补充出口 IP、代理错误码、流量和业务结果校验,避免把“HTTP 返回了结果”直接算成业务成功。

测试轮次 并发 总 QPS 成功 QPS 成功率 平均 / p95 407 / 429 / 5xx / 超时 流量或带宽 结论
基线 1 填写实测值 填写实测值 填写实测值 填写实测值 分别记录 填写实测值 基准
阶梯 A 填写并发 填写实测值 填写实测值 填写实测值 填写实测值 分别记录 填写实测值 继续 / 回退
阶梯 B 填写并发 填写实测值 填写实测值 填写实测值 填写实测值 分别记录 填写实测值 继续 / 回退

可复制的 Python 小规模测试脚本

这个示例刻意保持简单,不模拟生产环境中的持久连接池和复杂连接复用,因此结果只适合作为低并发基线,不应直接作为正式容量上限。示例使用 HTTP 代理,只用于你拥有或已获授权的测试地址。把代理地址和目标地址替换为真实测试参数,并从较低并发开始。

from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import requests

PROXY = "http://username:password@proxy-host:port"
TARGET_URL = "https://your-authorized-test-endpoint.example/health"
CONCURRENCY = 10
TOTAL_REQUESTS = 100
TIMEOUT_SECONDS = 15

proxies = {"http": PROXY, "https": PROXY}

def send_one(request_id):
    started = time.perf_counter()
    try:
        response = requests.get(
            TARGET_URL,
            proxies=proxies,
            timeout=TIMEOUT_SECONDS,
        )
        elapsed_ms = (time.perf_counter() - started) * 1000
        return {
            "http_ok": 200 <= response.status_code < 400,
            "status": response.status_code,
            "elapsed_ms": elapsed_ms,
        }
    except requests.RequestException as exc:
        elapsed_ms = (time.perf_counter() - started) * 1000
        return {
            "http_ok": False,
            "status": type(exc).__name__,
            "elapsed_ms": elapsed_ms,
        }

test_started = time.perf_counter()
with ThreadPoolExecutor(max_workers=CONCURRENCY) as executor:
    futures = [executor.submit(send_one, i) for i in range(TOTAL_REQUESTS)]
    results = [future.result() for future in as_completed(futures)]
total_seconds = time.perf_counter() - test_started

latencies = sorted(item["elapsed_ms"] for item in results)
http_success_count = sum(1 for item in results if item["http_ok"])
p95_index = max(0, int(len(latencies) * 0.95) - 1)

print("concurrency:", CONCURRENCY)
print("total_qps:", round(len(results) / total_seconds, 2))
print("http_success_qps:", round(http_success_count / total_seconds, 2))
print("http_success_rate:", f"{http_success_count / len(results):.2%}")
print("average_ms:", round(sum(latencies) / len(latencies), 2))
print("p95_ms:", round(latencies[p95_index], 2))
print("status_counts:", {
    str(status): sum(1 for item in results if item["status"] == status)
    for status in set(item["status"] for item in results)
})

代码中的 http_success_qpshttp_success_rate 只表示状态码处于 200—399,不能自动证明业务结果正确。实际任务还应增加响应内容校验,例如检查目标字段、JSON 业务状态或页面特征。这个脚本能做小规模基线核对,但不能代替完整压测平台;正式容量测试还要控制到达率、连接复用、预热时间、结果校验和测试中止条件,并由目标系统负责人确认允许的测试范围。

六、常见瓶颈与错误信号

测试现象 优先判断 处理方向
并发提高,成功 QPS 基本不变,p95 快速上升 某一层已经饱和,请求开始排队 回退并发,分别检查客户端、代理、带宽和目标响应
429 明显增加 目标服务正在执行速率限制 降低请求速率,遵守对方规则,并按 Retry-After 等提示等待
407 持续出现 代理认证信息缺失、错误或不完整 核对账号、密码、认证方式、有效期和配置位置
超时增加,但 CPU 与带宽仍有余量 地区链路、代理出口或目标服务响应可能波动 固定变量分地区复测,不要立即扩大线程池
CPU、内存或连接池先满 客户端先于代理达到容量上限 优化客户端资源和连接复用,再重新评估代理容量
错误率上升,同时流量消耗异常增加 失败重试、重定向或重复下载正在放大用量 限制重试次数,记录原始错误并核对单次请求大小

RFC 6585 对 429 的定义是单位时间内请求过多,响应还可能携带 Retry-After;它不等于“代理 IP 数量不够”。RFC 9110 对 407 的定义则指客户端需要向代理完成认证。把错误码分清,才能避免用增加 IP 或线程的方式处理一个认证问题。

七、测出瓶颈后,应该扩什么资源

扩容应跟着已经确认的瓶颈走。出口地址不够就扩 IP 池,持续吞吐碰到带宽上限就扩网络容量,需要固定出口或资源隔离时再调整代理类型;如果限制来自目标服务,继续增加代理和线程并不能解决问题。

已经确认的瓶颈或需求 应该调整的资源 增加什么可能无效 可考虑的方案
出口数量或地区覆盖不足 IP 池、地区资源和请求调度 单纯提高线程数 动态住宅代理
带宽持续接近上限,且客户端和目标服务仍有余量 网络带宽、服务器资源和连接配置 只增加出口 IP 数量 无限流量住宅代理
共享资源波动明显,需要可控的机房出口 独享出口、服务器、带宽及扩容方式 继续堆共享端口 独享数据中心代理
任务需要长期保持同一网络出口 IP 固定性、会话连续性和地区一致性 增加动态出口数量 静态住宅或其他固定出口方案
目标服务返回429或明确限制请求频率 降低到达率、遵守Retry-After并调整任务计划 增加IP、带宽或线程 不应通过代理扩容规避目标规则

确认瓶颈确实在出口数量和地区覆盖后,可以用 IPWeb 的动态住宅代理扩展轮换出口和并行会话;但“不限制并行会话数”不代表客户端、带宽和目标服务也没有边界。如果瓶颈是持续传输量和网络容量,无限流量住宅代理可以按服务器、带宽和 IP 数量等资源配置,再结合实际吞吐规划扩容。

如果重点是独享机房出口与可控资源,可以评估独享数据中心代理,并在询价时分别确认 IP、端口、带宽和服务器的资源边界。关于这四层资源为什么不能互相替代,可参考独享 IP、带宽、端口与服务器的区别

八、代理 IP 并发数常见问题

1. 100 个线程就等于 100 个代理并发吗?

不一定。线程可能在等待任务、执行解析或已经空闲,真正的代理并发要看同一时刻有多少请求尚未完成。异步程序中的协程数也不能直接等同于在途请求数。

2. 一个代理 IP 最多能开多少并发?

没有适用于所有目标和产品的统一数字。请求大小、响应时间、目标服务限制、代理网关、出口带宽和客户端资源都会影响结果。应从低并发开始,用真实授权目标做阶梯测试。

3. 无限并发是不是等于无限 QPS?

不是。代理服务不限制并行会话,只代表不会在该维度设置固定额度;实际 QPS 仍可能受客户端、网络带宽、代理出口、目标响应时间和目标服务规则限制。

4. 为什么带宽没有跑满,请求还是很慢?

带宽只是容量的一部分。高延迟、连接建立、目标处理时间、连接池等待和慢请求都可能让 QPS 先达到平台期,即使链路还有剩余带宽。

5. 提高并发以后出现 429,是代理不够吗?

通常不能这样判断。429 表示请求频率触发了目标服务的限制。应该降低到达率、读取对方返回说明并遵守 Retry-After,而不是继续增加线程或轮换出口。

6. 407 错误是并发过高造成的吗?

407 的标准含义是需要向代理完成认证。应先核对代理账号、密码、认证方式和资源状态;只有服务商明确说明并发超限也会返回该错误时,才按具体产品规则处理。

7. 代理 IP 数量增加后,并发能力会按比例增加吗?

不保证。增加出口 IP 可以改善任务分配和地址覆盖,但如果瓶颈位于客户端、共享网关、总带宽或目标服务,成功 QPS 不会随 IP 数量线性增长。扩容前应先通过测试确认真正的限制层。

计算代理 IP 并发时,先确定成功 QPS,再测端到端响应时间,最后用阶梯测试确认稳定点。如果并发继续增加却没有带来更多成功结果,就应该寻找瓶颈,而不是继续堆线程和出口 IP。