☰
JMeter+Fiddler抓包:代理配置与HTTPS证书排查实战
2026/11/2 4:15:20 网站建设 项目流程

项目脚本在 GUI 里跑得好好的,断言全绿,结果一到服务器侧看日志,发现请求体里少了字段、参数被多编码了一层、某个自定义 Header 压根没发出去。这种时候光盯着 JMeter 的 View Results Tree 是没用的,它只告诉你"返回了什么",不告诉你"实际发出了什么"。想看清这条链路,最直接的办法是把 Fiddler 塞到 JMeter 和被测服务中间,让每一个字节都从它眼皮底下过一遍。这篇就把"用 Fiddler 抓 JMeter 请求"这件事从头拆到尾:为什么 JMeter 默认绕过 Fiddler、三条把流量导进去的路子怎么挑、HTTPS 那道证书坎怎么迈、抓不到包时按什么顺序排查、抓到之后怎么把会话变成结论。适合刚接手接口脚本、被编码和证书问题折磨过的测试同学,也适合想搞明白代理机制的开发。

1. 先把原理捋顺:JMeter 的请求为什么天生绕开 Fiddler

1.1 JMeter 读的是 JVM 系统属性,不是操作系统的代理设置

很多人第一次做这件事的顺序是这样的:在系统设置里打开代理,指向 127.0.0.1:8888,然后浏览器访问网页,Fiddler 里哗哗出会话,心里一阵踏实。接着启动 JMeter 跑一遍脚本,回头一看 Fiddler,干干净净一条记录都没有。于是开始怀疑 Fiddler 坏了、端口被占、防火墙拦了,折腾半小时。

真相很简单:操作系统那一层的代理设置,只对遵循系统代理约定的程序生效,典型代表是浏览器这一类走系统网络栈的应用。JMeter 是跑在 JVM 上的 Java 程序,它的 HTTP 采样器底层用的是 Apache HttpClient,取代理信息的方式是读 JVM 的系统属性http.proxyHost、http.proxyPort、https.proxyHost、https.proxyPort,外加一份http.nonProxyHosts白名单。你在系统设置里改的东西,JVM 一个字节都读不到。Linux 和 macOS 下习惯性export HTTP_PROXY=...的做法同样不管用,因为 JMeter 的 HttpClient 并不去读环境变量。

这就解释了一个常见现象:同样的代理设置,浏览器能抓、curl 能抓、Postman 能抓,唯独 JMeter 抓不到。不是 JMeter 特殊,是它老老实实按 Java 的规矩走,而 Java 的规矩和你想象中的规矩不是一套。

记住这条:给 JMeter 配代理,配的是 JVM 系统属性,不是操作系统代理。这个认知错位是九成"抓不到包"问题的根。

1.2 Fiddler 在链路里扮演的角色,以及 HTTPS 时它做了什么手脚

Fiddler 本质上是个本地 HTTP 代理服务器,默认监听 8888 端口。当 JMeter 被配置成走127.0.0.1:8888之后,一条 HTTP 请求的走向会变成:JMeter 把请求行写成绝对地址形式(GET http://demo.internal.test/api/v1/items HTTP/1.1),发到 Fiddler;Fiddler 解析出真实主机,自己再和服务端建一条新连接,转发过去;服务端响应回来,Fiddler 再转回给 JMeter。

这里有个细节值得说清楚:JMeter 和 Fiddler 之间是一条 TCP 连接,Fiddler 和服务端之间是另一条。所以你在 Fiddler 里看到的连接耗时、TCP 握手信息,跟 JMeter 实际经历的网络路径并不完全一致,做性能分析时别看串了。

HTTPS 的流程要复杂一层。JMeter 首先向 Fiddler 发一条CONNECT demo.internal.test:443 HTTP/1.1,Fiddler 回HTTP/1.1 200 Connection Established,握手通道打通。紧接着 TLS 握手开始,此时 Fiddler 并不真的去和 JMeter 讲"我是代理",而是现场用自己签发的证书冒充demo.internal.test,把 TLS 会话先接住;然后它再去和真服务端完成另一次 TLS 握手,两头解密再加密,中间明文它自己留着看。这套机制能跑通的前提只有一个:JMeter 这一侧的 JVM 信任 Fiddler 那张根证书。否则 TLS 握手在证书校验环节就断了,你只能在 Fiddler 里看到一条孤零零的 CONNECT,看不到任何明文——这就是后面第 3 章要重点解决的事。

1.3 动手之前必须先问自己的三个问题

在敲任何命令之前,先把这三件事想明白,能省掉一大半返工。

第一,JMeter 和 Fiddler 是不是在同一台机器上。同机的话,代理地址填127.0.0.1就行,最省事。如果是 JMeter 跑在 Linux 压测机上、Fiddler 装在本地 Windows,那 Fiddler 必须打开"允许远程连接",并且在防火墙放行 8888,JMeter 侧填的是 Fiddler 所在机器的局域网 IP。跨机场景还要注意一点:流量会真的绕一圈,延迟和带宽都不代表真实情况。

第二,被测地址是不是本机或内网回环。Java 默认的http.nonProxyHosts里包含localhost|127.*|[::1]这类条目,意思是访问这些地址不走代理。如果你的脚本打的是本机起的服务,代理配了也白配,请求会规规矩矩地直连。这种情况需要把http.nonProxyHosts显式清空或改写。

第三,目标是不是 HTTPS,以及服务端证书是不是自签的。如果是自签证书,问题会变成双重的:JMeter 既要信任 Fiddler 的根证书,Fiddler 又要能接受服务端的自签证书。两层都得处理,缺一不可。很多人只处理了第一层,然后困惑为什么 Fiddler 里能看到请求但服务端返回 502。

2. 把 JMeter 流量导进 Fiddler 的三条路,按场景挑

2.1 命令行 -H 与 -P:临时调试最省事的一条路

JMeter 的命令行工具本身就带代理参数,这四个值得记住:

  • -H代理主机
  • -P代理端口
  • -N非代理主机列表(对应http.nonProxyHosts)
  • -u/-a代理的用户名和密码(代理需要认证时用)

一个最典型的不带界面的调用长这样:

# Windows 下在 JMETER_HOME/bin 目录执行 jmeter -n -t order_flow.jmx -l result.jtl \ -H 127.0.0.1 -P 8888 \ -N ""

Linux 下同理,注意-N ""在某些 shell 里会被吞掉,稳妥的写法是直接把非代理列表显式写成你不需要绕过的样子:

jmeter -n -t order_flow.jmx -l result.jtl \ -H 127.0.0.1 -P 8888 \ -N "no-such-host.invalid"

用-H/-P的好处是改动零侵入:脚本文件一个字都不用动,别人拿去做正式压测时也不会因为残留的代理配置把流量导到不存在的端口上。坏处是每条命令都得带着,容易忘;而且它只影响 HTTP/HTTPS 采样器,对 JDBC、JUnit、TCP 采样器无效——这点在混合场景里要留意,别指望它把所有流量都截下来。

还有一个容易忽略的优先级问题:如果某个 HTTP 请求采样器自己已经填了 Proxy Server 字段,那采样器级别的配置会覆盖命令行给的全局值。排查"为什么这条请求不走代理"时,先去采样器的 Advanced 面板看一眼,别一上来就怀疑命令行。

2.2 写进 system.properties:一次配置,所有启动方式都生效

如果你有一台专门用来调试脚本的机器,或者整个团队都用同一套环境,那把代理写进配置文件更合适。这里有个关键区分必须讲清楚,很多教程含糊带过,结果照抄了却不生效:

jmeter.properties里放的是 JMeter 自己的属性,system.properties里放的才是 JVM 系统属性。代理属于后者。你在jmeter.properties里写http.proxyHost=127.0.0.1基本是白写,因为 JMeter 不会把它当成 JVM 属性用。正确的落点是JMETER_HOME/bin/system.properties,追加这么几行:

# bin/system.properties http.proxyHost=127.0.0.1 http.proxyPort=8888 https.proxyHost=127.0.0.1 https.proxyPort=8888 # 清空非代理列表,避免打本机服务时被绕过 http.nonProxyHosts= https.nonProxyHosts=

改完重启 JMeter 才会生效,因为系统属性是在 JVM 启动时读入的,GUI 里面改不了。这也是它相对命令行的一个劣势:切换"抓包/不抓包"两种状态要改文件、要重启,不够灵活。好处是团队里谁拿到这台机器都能直接复现,不用记一长串参数。

提示:system.properties是共享文件,提交到代码库里之前先把代理配置注释掉或者删掉。我见过不止一次,某人调完脚本忘了删,第二天同事在另一台机器上跑同一套脚本,所有请求全部指向 127.0.0.1:8888,全线报连接拒绝,查了半天以为是服务挂了。

2.3 采样器级别填 Proxy Server:只抓你想抓的那一条

第三种方式颗粒度最细,在 HTTP 请求采样器的 Advanced 面板底部有 Proxy Server 一栏,填主机和端口即可。它最大的价值是"精准"——一个计划里如果有二十个接口,你只想查其中三个的请求体,就不必让全部流量都绕道代理,避免其他接口因代理引入的额外延迟和偶发失败干扰判断。

这里分享一个真正省事的技巧:不要对着每个采样器挨个填,用HTTP Request Defaults统一配一次就行。同一线程组里所有没单独覆盖该字段的 HTTP 采样器都会继承这个默认值。需要临时排除某一条时,再在那条采样器上单独清空该字段(或填一个非代理的空值)。这套做法比全局配置灵活得多,尤其是在一个测试计划里同时包含"要抓包的接口"和"纯压测的接口"时。

三种方式放在一起对比,大致是这样:

方式生效范围改动成本适合场景主要坑点
命令行-H/-P全局,仅 HTTP/HTTPS 采样器低,不改文件临时调试、无界面运行每次都要带参数;易忘
system.properties全局,所有启动方式中,需重启固定调试机、团队共用环境误提交;对 JMeter 属性/系统属性混淆
采样器 Proxy Server精确到单条请求高,但可用 Defaults 摊薄混合场景,只抓部分接口逐条填写易漏;优先级高于全局

选择逻辑其实很简单:一次性排查走命令行,长期固定环境走配置文件,只想看几条请求走采样器加 Defaults。

3. HTTPS 才是真正的坎:让 JMeter 的 JVM 信任 Fiddler 的根证书

3.1PKIX path building failed到底在抱怨什么

代理配好第一次跑 HTTPS 脚本,十有八九会在 JMeter 的日志里撞见这几行:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

直译一下就是:JVM 拿着服务端递过来的证书,想沿着签发链一路往上追到某个自己信任的根,追到一半断了,找不到可信的锚点。因为此刻递给它证书的"服务端"其实是 Fiddler 假扮的,签发者是 Fiddler 自己生成的根证书,而 JVM 的信任库(cacerts)里压根没有这张证书。

注意这个报错跟"证书过期""域名不匹配"完全是两回事,别顺着那几个方向查。判断方法很直接:把代理关掉、让 JMeter 直连同一个地址,如果请求恢复正常,那就百分百是信任链的问题,而不是服务端证书本身有问题。

顺带说一个高频误区:很多人以为在 Fiddler 里点了"Decrypt HTTPS traffic"、点了"Trust Root Certificate",问题就解决了。这两个动作只把 Fiddler 的根证书装进了Windows 的证书存储区,让浏览器和走系统证书库的程序信任它。JVM 用的是自己的cacerts文件,跟 Windows 证书库是两套东西,井水不犯河水。所以浏览器抓 HTTPS 一片绿,JMeter 抓 HTTPS 一片红,是完全正常的。

3.2 导出 Fiddler 根证书并用 keytool 建一个独立信任库

第一步,把 Fiddler 的根证书导出来。在 Fiddler 里依次进入 Tools → Options → HTTPS,点 Actions,选择 Export Root Certificate to Desktop,桌面上会多出一个FiddlerRoot.cer。

第二步,用 JDK 自带的keytool把它导进一个新建的信任库。这里强烈建议新建而不是直接往 JDK 的cacerts里塞,理由后面说。

# 先确认 keytool 可用,路径要和 JMeter 用的 JDK 一致 keytool -version # 新建信任库并导入 Fiddler 根证书 keytool -importcert -noprompt \ -alias fiddlerroot \ -file FiddlerRoot.cer \ -keystore fiddler-truststore.p12 \ -storetype PKCS12 \ -storepass changeit

几个参数值得解释一下。-alias是这条证书在库里的别名,起个能认出来的名字,将来要删的时候方便。-noprompt表示不交互确认,脚本化时必备。-storetype PKCS12是因为新版本 JDK 早就不用 JKS 作为默认格式了,显式写清楚能避免老教程和新环境对不上号。-storepass设的密码在下面挂参数时要用到,别设成自己都记不住的东西。

为什么不建议直接往cacerts里塞?因为那是整个 JDK 的全局信任库,你往里面加了一张 Fiddler 的根证书,等于这台机器上所有 Java 程序都无条件信任它签发的任何证书。调试期无所谓,但如果这台机器还跑着别的服务,或者团队里有多人共用,这个改动的影响面就太大了,而且事后很容易忘掉自己改过。单独建一个 truststore、只在需要抓包的那次启动里挂上去,是干净得多的做法。

注意:keytool必须用 JMeter 实际使用的那套 JDK 里的。机器上装了多个 JDK 是常事,用 A 的 keytool 生成信任库、JMeter 却跑在 B 上,虽然 PKCS12 格式通用一般不会出问题,但版本差异带来的算法兼容问题偶尔会咬人。用jmeter -v能看到它用的 Java 版本和路径。

3.3 把信任库挂到 JMeter 启动参数上的两种写法

有了信任库,接下来要把路径告诉 JVM。两个系统属性:

  • javax.net.ssl.trustStore信任库文件路径
  • javax.net.ssl.trustStorePassword信任库密码

写法一,命令行临时挂:

jmeter -n -t order_flow.jmx -l result.jtl \ -H 127.0.0.1 -P 8888 \ -Djavax.net.ssl.trustStore=/path/to/fiddler-truststore.p12 \ -Djavax.net.ssl.trustStorePassword=changeit

注意这里是-D不是-J。JMeter 的命令行里,-D设的是 Java 系统属性(直接进 JVM),-J设的是 JMeter 自己的属性。搞混了就是"参数写了但没生效"的经典来源。Windows 下路径建议用正斜杠D:/tools/fiddler-truststore.p12,反斜杠容易被当成转义符。

写法二,写进bin/system.properties:

javax.net.ssl.trustStore=D:/tools/fiddler-truststore.p12 javax.net.ssl.trustStorePassword=changeit

同样需要重启生效。这条写法和第 2.2 节的代理配置放在一起,就构成了一套完整的"抓包模式"配置,用的时候打开、不用的时候注释掉,比每次记命令行靠谱。

配好之后重新跑,如果 Fiddler 里能看到完整的 HTTPS 请求和响应明文,Inspectors里能查看到请求体,那就通了。如果还是握手失败,先确认信任库路径没写错(-D参数里路径有空格会截断,尽量放在无空格的目录),再确认keytool列出来的内容里确实有那条别名:

keytool -list -keystore fiddler-truststore.p12 -storepass changeit

3.4 服务端用自签证书时的第二层信任

上一节解决的是"JMeter 信任 Fiddler"。如果被测服务端自己用的也是自签或内部 CA 签发的证书,那 Fiddler 这一侧还得能接受它,否则 Fiddler 转发时照样报错,通常表现为 Fiddler 会话变红、状态码 502。

处理办法是把服务端那张证书也导进同一个信任库,用不同的别名:

keytool -importcert -noprompt \ -alias targetserver \ -file server-cert.cer \ -keystore fiddler-truststore.p12 \ -storetype PKCS12 \ -storepass changeit

因为 Fiddler 和 JMeter 共用同一套 JVM 信任配置(Fiddler 本身跑在 .NET 上,但它的证书校验走系统证书库,所以严格说是两边都要处理)。更省事的替代方案是在 Fiddler 的 HTTPS 选项里勾选"忽略服务端证书错误",只在你明确知道目标环境是内网测试环境时用,别把这个开关带到任何对外的场景里。

还有一条更轻量的路子:如果这次调试只关心请求体长什么样,完全不需要解密,那就在 Fiddler 的 HTTPS 设置里关掉"Decrypt HTTPS traffic",让它只做隧道透传。好处是不用碰证书,坏处是看不到任何明文,只能看到 CONNECT 和字节数。什么时候够用?当你的问题是"请求到底发没发出去""有没有重试""连接耗时多少"时,透传就够了。

4. 抓不到、抓一半、抓到假的:典型故障的排查链路

4.1 会话列表一片空白,一条记录都没有

按顺序往下排,不要跳步。

第一层,Fiddler 到底有没有在监听。看 Fiddler 左下角状态栏,正常会显示Capturing和监听端口。如果显示的是Capturing但端口不对,去 Tools → Options → Connections 确认。顺手看一眼"Allow remote computers to connect"——跨机场景必须勾上,勾上之后 Fiddler 会提示需要重启才生效,很多人就是漏了这步重启。

第二层,JMeter 的代理配置到底有没有进去。最可靠的验证方式是看 JMeter 日志开头有没有相关输出,或者在脚本里加一个"查看结果树",看响应头里有没有 Fiddler 附加的痕迹。更直接的办法:故意把代理端口写成一个没人监听的端口(比如 8899),如果请求立刻报Connection refused,说明代理配置确实生效了,只是端口不对;如果请求照样成功返回,说明代理配置压根没被读到——那就回头检查是-H参数位置写错了,还是改的是jmeter.properties而不是system.properties。

第三层,流量被 nonProxyHosts 悄悄放行了。这个最阴。表现是:代理配置正确、端口正确、Fiddler 也在监听,但就是没有会话。原因是被测地址命中了 Java 默认的非代理白名单。验证方法很简单,把http.nonProxyHosts显式清空再试一次。第 1.3 节提过这个坑,但它值得重复一遍,因为它不属于"配置错误",配置本身是对的,只是被另一条规则覆盖了,从表面看不出来。

第四层,IPv6 与 DNS 解析顺序。极少数情况下,JMeter 解析域名拿到的是 IPv6 地址,而代理配置里写的是 IPv4 的回环,连接行为会变得难以预测。把代理地址写成127.0.0.1而不是localhost,能规避掉这一类玄学问题。

4.2 只看到 CONNECT 隧道,看不到任何明文

这个现象非常有辨识度:Fiddler 会话列表里出现一条CONNECT demo.internal.test:443,状态是 200,然后就没了,展开也只有一个空壳。同时 JMeter 那边的响应可能是 200 也可能直接失败。

这就是典型的"TLS 握手在证书校验环节被拒"。Fiddler 想解密,但 JMeter 不认它的证书。回到第 3 章,检查三件事:信任库路径对不对、密码对不对、信任库里到底有没有那张 Fiddler 根证书。三样都对了还不行,就要看 JMeter 启动时是不是被别的参数覆盖了——比如某些启动脚本里预置了javax.net.ssl.trustStore,你命令行又传了一个,最终谁生效取决于顺序,很容易误判。

还有一种情况容易被误认为证书问题:Fiddler 的 HTTPS 解密没开。Tools → Options → HTTPS 里那两个勾选框(Capture HTTPS CONNECTs、Decrypt HTTPS traffic)只要有一个没勾,你就会看到一堆 CONNECT 而没有明文。这个检查花不了十秒钟,但很多人因为"我明明记得勾了"而跳过它,最后绕了一大圈。

4.3 抓到的请求和 JMeter 里看到的对不上

这类问题最考验判断力,因为现象是"抓到了,但内容不对劲"。常见的三种走样:

压缩与编码。Fiddler 的 Inspectors 里如果看到一堆乱码,先看响应头有没有Content-Encoding: gzip。JMeter 默认会带Accept-Encoding: gzip,deflate,Fiddler 抓到的是压缩后的原始字节,需要在 Inspectors 里点一下解码按钮才能看明文。别看到乱码就以为请求体传错了。

重定向与跟随。JMeter 的 HTTP 请求采样器默认勾选"Follow Redirects",一条逻辑上的请求在 Fiddler 里会展开成三条会话(301 → 302 → 200)。如果你按"会话条数"去数请求数,必然对不上。看的时候认准第一条的 Request 和最后一条的 Response,中间的跳转本身也是要检查的对象——有时候问题恰恰出在某个中间跳转把 Header 丢掉了。

代理引入的额外头。走代理之后,请求头和响应头里会多出一些原本不存在的东西,比如Via、X-Forwarded-For之类。如果服务端有严格的 Header 白名单校验,或者有基于来源 IP 的风控逻辑,这些多出来的头可能直接导致行为变化。所以抓包环境验证通过,不代表正式环境也通过,这一点在第 6 章还会展开。

4.4 一开 Fiddler,压测数据就崩了

这个问题属于"操作正确但用错了场合"。Fiddler 作为中间人,每条请求都要建立两条 TCP 连接、做两次 TLS 加解密、做一次完整的内存缓冲和解析,吞吐能力跟直连完全不在一个量级。你拿它去跑几百上千并发,得到的 TPS 反映的是 Fiddler 的处理能力,不是被测系统的。

正确的用法是把抓包严格限定在功能调试阶段:单线程、单次迭代、只跑你想查的那几条请求。等请求内容确认无误,关掉代理、清掉配置,再去做性能测试。如果确实需要在压测中观察流量特征,应该换用抓包工具的网络层方案或者服务端侧的日志采样,而不是让所有流量都从 Fiddler 走一遍。

还有一种更隐蔽的影响:某些服务的连接池行为会因为代理而改变。直连时 JMeter 可能复用连接,走代理后连接建立与关闭的模式变了,服务端的连接数统计、限流策略都可能被触发,从而产生"抓包时能复现、不抓包时复现不了"的诡异问题。遇到这类现象,先怀疑代理本身改变了行为,别急着给被测系统提缺陷。

5. 抓到之后怎么用:从会话里把结论抠出来

5.1 Inspectors 里到底该盯哪几块

Fiddler 的 Inspectors 面板上下分栏,上面是请求、下面是响应,每一栏又有多个视图。实战中最常看的是这三个:

Raw 视图。它把实际在网络上传输的字节原样呈现,包括请求行、所有 Header、空行、Body。判断"JMeter 到底发了什么"要看这个,而不是 Headers 视图——Headers 视图会做美化,偶尔会隐藏掉一些重复的头或者异常的换行。

Headers 视图配合 WebForms。WebForms 会把application/x-www-form-urlencoded的 Body 拆成键值对展示,对照参数特别方便。但要注意它对编码的处理:中文参数如果被 URL 编码成了%E4%B8%AD,WebForms 可能显示成解码后的样子,看起来一切正常,实际上服务端收到的是另一回事。所以要确认编码问题时,必须回到 Raw 视图去看原始的百分号编码。

TextView 与 HexView。前者看文本 Body,后者看二进制。上传文件、图片、protobuf 这类请求,TextView 里是乱码,HexView 里才能确认字节数对不对。

一个实用习惯:在 Fiddler 里用Ctrl+F搜索关键字,比在长列表里肉眼找快得多。查某个参数有没有发出去,直接搜参数名。

5.2 用 Composer 重放,把变量一个个隔离出来

看清楚了请求长什么样,下一步是验证"是不是这个变量导致的问题"。Fiddler 的 Composer 面板可以把你选中的会话直接拖进去,改一个参数重发一次,对比响应差异。这个能力在排查参数编码、Header 缺失、签名错误时特别好用,因为它完全绕开了 JMeter,能快速确认问题到底出在脚本层还是服务端层。

举一个实际场景。某次接口一直返回参数校验失败,JMeter 的 View Results Tree 里看着参数都是对的。把请求拖进 Composer 一看,发现表单里有中文参数被编码成了%25E4%25B8%25AD这种双重编码的形式——多了一层%25。原因出在脚本里先用函数做了一次编码,采样器又勾了编码选项,编了两次。这种问题不抓包根本看不出来,因为 JMeter 界面上显示的是解码后的值。定位之后,在采样器上取消编码选项就解决了。

Composer 的另一个用法是做"最小可复现请求":把抓到的完整请求精简到只剩必要参数和必要 Header,看服务端还认不认。这一步能帮你准确界定"服务端到底依赖哪些字段",反过来优化脚本里多余的配置。

5.3 把差异做成对照组,而不是凭感觉猜

真正高效的排查方式不是"看一眼觉得不对",而是构造对照组。做法是:保持其他一切不变,只改一个变量,跑两次,把两次的 Fiddler 会话并排对比。

Fiddler 自带会话对比功能,选中两条会话,右键 Compare Session,会用 diff 的方式把请求头、请求体、响应头的差异高亮出来。这个功能在排查"为什么这条成功那条失败"时非常省时间——肉眼逐行看两个几百行的报文,几乎必然会漏。

对照组的变量可以是:一个特定的 Header 加与不加、参数编码方式改与不改、Cookie 带与不带、请求方法 GET 与 POST。每次只动一个,结论才干净。我见过太多人在一次实验里同时改了三处,结果问题消失了也不知道是哪一处起的作用,下次换个场景又踩一遍。

6. 踩过才知道的几条经验

6.1 端口冲突与"回环监听"的隐形门槛

Fiddler 默认端口 8888 被占的情况比想象中常见——开发工具、其他调试代理、某些本地服务都可能占用它。表现是 Fiddler 启动时弹窗提示端口被占,但很多人点掉之后继续用,以为它自动换了个端口就行。实际上改端口之后 JMeter 侧的-P参数也得跟着改,两头不一致的话,表现就是连接被拒,而错误信息又完全不提端口的事。

换个端口不难,在 Tools → Options → Connections 里改一个 8000 以上的空闲端口,记得同步改 JMeter 侧配置。

另一条经验是监听地址。Fiddler 的监听默认绑在所有网卡上,Windows 第一次启动时通常会弹防火墙提示,很多人习惯性点了"取消"或者直接关掉弹窗。后果是跨机场景下,JMeter 所在的机器连不上 Fiddler 的端口。这种问题的迷惑性在于"同机测试完全正常",只有跨机才出问题,很容易误判成网络不通。真遇到跨机连不上,先在 JMeter 那台机器上用telnet <fiddler-ip> 8888试一下端口通不通,一秒钟排除掉一大类可能。

6.2 连接复用和 Keep-Alive 会让会话数对不上

前面提过重定向会让会话数膨胀,这里说反向的情况:会话数比预期少。

原因通常是连接复用。JMeter 的 HttpClient4 默认会保持连接,一条 TCP 连接上可以跑多条请求。Fiddler 抓到的是连接层面的会话,虽然它会把同一连接上的多条请求分别列出,但如果你在数"发了多少次"时把连接建立次数当成了请求次数,就会对不上。

更需要注意的是另一种影响:某些场景下你想验证"服务端是否支持长连接",结果因为走了代理,代理自己的连接管理策略介入进来,得到的结论并不可靠。判断连接复用相关问题,最好在 Fiddler 的 Timeline 或 Statistics 视图里看时间线,那里能看到每条请求在连接上的位置,比单纯看条数直观得多。

6.3 抓包环境和压测环境必须物理隔离

这条是反复吃亏换来的。抓包时要改system.properties、要挂信任库、可能要临时忽略证书校验,这些改动如果和正式压测共用一份配置,早晚出事。

最典型的事故是信任库:调试期为了图方便,把 Fiddler 根证书导进了机器上所有 Java 程序共用的信任库。事后忘了清理,某天这套环境被拿去做别的事情,等于给这台机器开了一个谁都能利用的信任后门。虽然内网环境风险有限,但这类"临时改动被固化"的习惯本身就是隐患。

我自己的做法是准备两套启动脚本:jmeter-debug.sh里带上全部抓包参数,jmeter-run.sh里干干净净什么都不带。切环境靠换脚本,不靠改配置文件。配置类的东西一旦需要人记住"现在是什么状态",迟早会出错。

另外,抓包期间产生的.jtl结果文件不要直接拿去出报告。代理引入的延迟会污染响应时间指标,样本量又小,统计意义接近于零。抓包产出的价值是"看清了请求内容",不是"测出了性能数字",这两件事老老实实分开做。

最后分享一个判断时机的小技巧:当你在纠结"要不要抓个包看看"的时候,答案基本都是要。因为猜请求内容这件事,猜对的概率远低于你的直觉。抓一次,五分钟,比对着脚本逐行推演半小时靠谱得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询