当负载测试遇到速率限制、WAF 或地理负载均衡时,第一反应是“我将从不同的 IP 发起流量”。听起来合乎逻辑,但在实践中,k6 和 JMeter 中的代理仅能解决有限的问题,其余的仍需通过测试架构来修复。本文将探讨如何技术性地将代理连接到这两个工具,适合的 IP 类型,以及代理服务器的责任范围在哪里。
负载测试为何需要不同的 IP
默认情况下,k6 和 JMeter 从一个 IP 地址(即运行测试的服务器或 CI/CD 中的云机器)发送所有流量。这对于 90% 的场景是正常的,但在某些情况下,一个 IP 是不够的:
- 基于 IP 的速率限制。 许多 API 和负载均衡器(nginx limit_req、AWS WAF、Cloudflare)限制来自同一地址的请求数量。真实用户来自成千上万的不同 IP,而你的测试只用一个 IP — 这会在达到真实应用瓶颈之前就碰到限制。
- 测试地理依赖的逻辑。 CDN、定向内容、区域性定价、地理封锁 — 所有这些都需要使用来自特定国家的 IP 来检查,而不是来自物理上放置测试运行器的数据中心。
- 检查负载均衡器和 anycast 网络。 如果基础设施根据客户的 IP 分配流量,来自一个地址的测试只会检查一条路径,而不是整个网络。
- 模拟真实的流量分布。 生产流量的 IP 分布在不同的提供商、子网,有时还包括移动运营商 — 这会影响 CDN、缓存和边缘逻辑的行为。
重要的是要立即划分:如果你正在测试后端的性能(你的 API 能承受多少 RPS),几乎不需要代理 — 重要的是纯粹的负载,而不是来源的多样性。当测试场景确实依赖于客户的 IP 地址时,代理才是必要的。
适合的代理类型:数据中心、住宅、移动
代理类型的选择直接影响你测试的内容 — 是基础设施的带宽还是系统在“真实” IP 下的行为。
| 代理类型 | 延迟和速度 | 何时在负载测试中使用 |
|---|---|---|
| 数据中心代理 | 低延迟,高带宽 | 检查速率限制,绕过“每个 IP N 个请求”的限制,从不同子网生成大量 RPS |
| 住宅代理 | 延迟较高,速度受真实用户的带宽限制 | 测试地理逻辑,检查 CDN 和反机器人系统,这些系统对住宅范围的信任度高于数据中心 |
| 移动代理 | 最高延迟,不稳定的速度 | 小众场景:测试移动 API,频繁更换 IP 时的行为(运营商动态更改客户地址) |
对于纯粹的 RPS 和速率限制检查,几乎总是足够使用数据中心代理 — 它们提供稳定的低延迟,并且不会因外部网络不稳定而扭曲测试结果。住宅和移动 IP 在地理测试中增加了现实感,但也带来了自身的延迟,在分析指标时必须考虑 — 否则很容易将“代理网络延迟”与“你的服务器延迟”混淆。
在 k6 中设置代理
k6 是一个基于 JavaScript 的工具(引擎用 Go 编写,脚本用 JS 编写),默认情况下没有通过脚本选项内置的 HTTP 代理支持:k6 中的代理通过环境变量或系统设置来指定,因为 k6 在底层使用 Go HTTP 客户端。
最简单的方法是使用环境变量:
export HTTP_PROXY="http://login:password@proxy-host:port"
export HTTPS_PROXY="http://login:password@proxy-host:port"
k6 run script.js
这种方法会将测试的所有流量通过一个代理 — 如果你只是想离开服务器的“白” IP,这种方法是合适的。但如果任务是将虚拟用户(VU)分配到不同的 IP,则需要一个代理列表和脚本级别的选择逻辑。k6 并不直接支持每个 VU 的代理,因此一种常见的变通方法是并行启动多个 k6 进程,每个进程都有自己的环境变量和来自池的代理:
// run-with-proxies.sh
PROXIES=("proxy1:port" "proxy2:port" "proxy3:port")
for proxy in "${PROXIES[@]}"; do
HTTP_PROXY="http://user:pass@$proxy" \
HTTPS_PROXY="http://user:pass@$proxy" \
k6 run --vus 50 --duration 5m script.js &
done
wait
这种方法与 k6 Cloud 或通过 Kubernetes/Docker Compose 的编排良好扩展 — 每个容器都有自己的代理变量。如果需要在单次脚本运行中进行 IP 轮换,最好从代理提供商那里获取带有轮换的代理(具有 TTL 的粘性会话),而不是在 JS 代码中进行轮换。
在 JMeter 中设置代理
在 JMeter 中,代理是通过 HTTP Request Defaults 元素或直接在 HTTP Request Sampler 的设置中原生配置的,无需环境变量:
- 在线程组中添加配置元素 HTTP Request Defaults。
- 在 Proxy Server 字段中指定代理的主机和端口。
- 如果代理需要身份验证 — 添加 HTTP Authorization Manager 元素,输入该主机的用户名和密码。
- 线程组内的所有 HTTP Request Samplers 将自动继承代理设置。
为了在 JMeter 中通过多个代理分配负载,使用 CSV Data Set Config 很方便 — 一个包含代理列表的文件被插入到每个线程的主机和端口变量中:
proxy_host,proxy_port,proxy_user,proxy_pass
proxy1.example.com,8000,user1,pass1
proxy2.example.com,8000,user2,pass2
proxy3.example.com,8000,user3,pass3
将 CSV Data Set Config 连接到线程组,在 Proxy Server/Proxy Port 采样器字段中指定变量 ${proxy_host} 和 ${proxy_port} — 每个 JMeter 线程将从文件中获取自己的行并通过自己的 IP 进行请求。对于通过命令行启动(无头模式,推荐用于实际负载测试)的情况,代理也可以通过标志传递:
jmeter -n -t test_plan.jmx -l results.jtl \
-H proxy-host -P port \
-u username -a password
这种方法为整个测试指定了一个通用代理 — 对于多代理场景,仍然需要使用 CSV Data Set Config 或分布式测试(多个 JMeter 从属,每个从属在配置中都有自己的代理)。
IP 轮换和负载分配
在负载测试中,有两种根本不同的 IP 分配方法:
- 静态 IP 绑定到线程/VU。 每个虚拟用户在整个会话中都获得相同的 IP — 模拟一个地址的真实用户。通过粘性会话代理或简单的 CSV/环境变量中的固定列表进行配置。
- 每个请求轮换 IP。 代理在每个 HTTP 请求中更改出站地址 — 对于检查速率限制的保护很有用,但并不能真实反映用户的实际行为,因为用户的 IP 并不会每秒更改一次。
对于现实的负载测试,在 90% 的情况下,将 IP 绑定到 VU/线程在整个会话中是更合适的 — 这样测试诚实地反映了众多独立用户的行为,而不是制造人造噪音。仅在狭窄的场景中才有意义在每个请求中启用轮换 — 例如,在针对速率限制规则的特定检查中。
代理绝对无法替代的内容
这里是文章的关键点:代理解决了“请求来自哪个 IP”的问题,但并没有解决负载测试实际上要检查的问题。
- 测试运行器的带宽。 如果负载生成器(运行 k6/JMeter 的机器)受限于 CPU、内存或网络接口 — 代理无法解决这个问题。代理增加了额外的网络跳数和自身的延迟,而不是减轻运行器的负担。
- 被测试服务器的真实带宽。 服务器要么承受负载,要么不承受 — 客户端的 IP 地址对此没有影响,除非明确的 IP 速率限制。
- 响应时间指标的准确性。 代理增加了自身的延迟(尤其是住宅和移动代理),这将作为响应时间的一部分出现在你的报告中。如果不单独减去代理的延迟,最终的延迟报告将被扭曲,并且不适合与生产指标进行比较。
- 基础设施在真实流量下的扩展能力。 带有代理的负载测试显示了在特定请求模式下的行为,但并不能替代基于真实生产日志的容量规划、自动扩展和负载配置。
- 在负载下检查业务逻辑的正确性。 竞争条件、数据库锁定、队列降级 — 这些问题需要通过并发测试和性能分析来解决,而不是通过更改出站 IP。
代理是一个用于特定任务的工具,“模拟来自不同 IP 的流量”,而不是负载测试的通用增强器。如果目标是了解后端能够承受多少 RPS,在大多数情况下,代理根本不需要:只需几个没有代理的测试运行器,正确设置的保持活动和连接池即可。
通过代理测试时的典型错误
在实践中,大多数与代理相关的负载测试问题归结为几个重复的错误。
- 将代理延迟与被测试服务的延迟混淆。 如果没有基准测量(直接请求而不使用代理),无法了解代理服务器自身增加了多少毫秒。
- 在需要纯粹带宽的地方使用移动或住宅代理。 这些代理受限于最终设备的真实带宽,物理上无法承受数万 RPS — 对于纯负载,需要使用数据中心代理。
- 对于大量 VU,IP 池不足。 如果 5000 个虚拟用户只有 10 个代理地址,测试仍然会遇到相同的速率限制,只是延迟更高 — 服务会很快看到“10 个 IP,数千个请求”的模式。
- 忽视代理端的超时。 在高并发负载下,代理服务器可能会开始拒绝连接 — 重要的是提前确认代理提供商的并发会话限制。
- 在没有检查白名单/授权的情况下启动测试。 如果代理需要 IP 授权,而测试从具有动态地址的运行器的 CI/CD 启动 — 请求将因 407 Proxy Authentication Required 而失败,测试结果将毫无意义。
测试前检查清单
- 确定任务是否确实需要不同的 IP,或者一个地址的测试是否足够。
- 根据任务选择代理类型:数据中心用于 RPS 和速率限制,住宅/移动用于地理逻辑。
- 进行没有代理的基准测量,以将网络延迟与代理延迟分开。
- 检查代理提供商在所需 VU 水平下的并发连接限制。
- 设置代理的身份验证(用户名/密码或运行器的 IP 白名单)。
- 决定是否需要在 VU 上进行粘性会话或每个请求的轮换。
- 在进行完整测试之前,在短时间内(1-2 分钟)运行测试,以检查配置。
结论
在 k6 和 JMeter 中,代理是模拟来自不同 IP 地址的流量、检查速率限制和地理依赖逻辑的有效方法。但这并不能替代合理的负载测试规划:代理并不检查或改善服务器的带宽、后端在并发负载下的稳定性和真实的容量规划。请有针对性地使用它们 — 在测试确实依赖于客户的 IP 地址的地方,而不是作为“公平性”的通用工具。
如果任务是检查 IP 限制并模拟高带宽的海量流量,合理的起点是 数据中心代理 — 它们提供最低的延迟并支持大量并发会话。对于与地理逻辑和反机器人系统对流量来源的信任相关的测试,住宅代理 更为合适,而对于与移动流量相关的小众场景,移动 IP 是更好的选择。