1. JMeter请求重复现象解析
最近在性能测试过程中,我发现一个奇怪的现象:JMeter脚本明明设置了只运行一次,但在结果树中却偶尔会出现两次相同的请求记录。这种情况在HTTP/HTTPS协议测试中尤为常见,特别是当测试目标涉及重定向或安全验证时。
从技术角度来看,JMeter作为Apache旗下的开源压测工具,其请求发送机制与浏览器存在本质差异。浏览器会自动处理重定向、证书验证等环节,而JMeter则需要显式配置相关参数。当遇到302重定向、HTTPS证书校验或安全风控策略时,就可能出现"一次脚本执行,多次请求记录"的情况。
提示:这种现象在测试哔哩哔哩、淘宝等具有复杂安全策略的网站时尤为常见,错误日志中常会出现"触发安全风控策略,请求被拒绝"的提示。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 常见原因排查手册
2.1 自动重定向与跟随重定向
JMeter的HTTP请求组件中有两个关键配置项:
- 自动重定向(Auto Redirects):仅跟随302响应,但将重定向请求合并到原始请求的统计中
- 跟随重定向(Follow Redirects):完全模拟浏览器行为,会记录每个重定向步骤
java复制// 典型的重定向响应头
HTTP/1.1 302 Found
Location: https://new.location/path
当启用"跟随重定向"时,一个HTTP请求可能产生如下请求链:
- 原始请求 GET http://example.com
- 重定向请求 GET https://example.com (HTTP→HTTPS强制跳转)
- 最终请求 GET https://example.com/?sessid=xxx (会话跟踪)
2.2 HTTPS安全握手过程
HTTPS连接建立过程中可能触发多次请求:
- TCP三次握手
- TLS握手(ClientHello/ServerHello)
- 证书验证(OCSP Stapling检查)
- 应用层请求
在JMeter中,若未正确配置HTTPClient实现,可能会将握手过程记录为独立请求。建议对比以下两种配置:
- HTTPClient3.1(旧版,行为保守)
- HTTPClient4(新版,支持更精细的控制)
2.3 采样器逻辑错误
检查测试计划中是否存在:
- 意外的循环控制器(Loop Controller)
- 模块控制器(Module Controller)重复调用
- 逻辑控制器(Logic Controller)配置错误
xml复制<!-- 错误示例:无意识的循环结构 -->
<ThreadGroup>
<LoopController loops="1"/>
<HTTPSampler/>
<ModuleController/>
</ThreadGroup>
3. 诊断与解决方案
3.1 使用监听器定位问题
推荐组合使用以下监听器:
- View Results Tree:查看原始请求/响应
- Debug Sampler:输出变量状态
- Simple Data Writer:记录详细时序
重点关注字段:
sampleCount(实际采样次数)threadName(线程编号)timeStamp(精确到毫秒的时间戳)
3.2 配置优化方案
在HTTP请求默认值中设置:
properties复制http.redirect.ignore=true
https.sessioncontext.shared=true
httpclient.reset_state_on_thread_group_iteration=true
对于需要重定向的场景,建议显式处理:
java复制if (prev.getRedirectCount() > 0) {
sampleResult.setSampleLabel(prev.getSampleLabel() + "_Redirect");
}
3.3 证书问题专项处理
当遇到"安全证书"错误时:
- 导入目标站点证书到JMeter信任库:
bash复制keytool -import -alias example -keystore /path/to/jmeter/bin/ApacheJMeterTemporaryRootCA.crt
- 在HTTP请求中启用:
properties复制https.use.cached.ssl.context=true
4. 高级场景分析
4.1 风控策略应对方案
对于哔哩哔哩等严格风控平台:
- 添加合法的User-Agent:
http复制User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
- 模拟完整浏览器指纹:
java复制// 在BeanShell预处理中添加
vars.put("header_Accept-Language","zh-CN,zh;q=0.9");
vars.put("header_Sec-Fetch-Site","same-origin");
4.2 文件上传特殊处理
当测试文件上传接口时(Content-Type: multipart/form-data):
- 必须使用HTTPClient4实现
- 显式设置编码:
properties复制http.encoding=UTF-8
http.post.file.encoding=UTF-8
- 在请求头中精确指定:
http复制Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
4.3 分布式测试注意事项
在Master-Slave模式下:
- 确保所有节点时间同步(NTP服务)
- 统一各节点的JMeter版本和插件
- 在jmeter.properties中配置:
properties复制server.rmi.ssl.disable=true
client.rmi.localport=60000
我在实际压测淘宝商品详情页时(类似热词中的URL结构),发现需要特别处理:
- 解码URL中的百分号编码:
java复制String decoded = URLDecoder.decode("https%3a%2f%2fmain.m.taobao.com%2fdetail%2findex.html", "UTF-8");
- 处理动态生成的
_tb_token_参数 - 添加X-Requested-With头:
http复制X-Requested-With: XMLHttpRequest
对于502 Bad Gateway错误(如热词中的127.0.0.1:15721案例),建议:
- 增加HTTP请求超时设置:
properties复制http.request.timeout=60000
- 添加重试逻辑:
xml复制<RetryLogic retryCount="3" retryDelay="1000"/>
- 检查后端服务日志,确认是否是JMeter请求过载导致
最后分享一个实用技巧:在测试CSDN等使用跳转链接的网站时(如热词中的links.jianshu.com案例),可以使用正则表达式提取器捕获最终URL:
regex复制location.href\s*=\s*["'](https?://[^"']+)["']
对于需要处理Cookie的场景,建议:
- 启用Cookie管理器
- 设置合理的Cookie策略:
properties复制CookieManager.check.cookies=false
CookieManager.save.cookies=true
- 对于跨域场景额外配置:
properties复制CookieManager.allow_variable_cookies=true
