ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JMeter低频压测实战:如何稳定实现每秒1次请求

JMeter低频压测实战:如何稳定实现每秒1次请求 先说个有意思的事。很多人一听到“压测”两个字脑子里浮现的都是几百上千并发、TPS 好几千的宏大场面。但实际工作中我接到过不少需求恰恰相反——客户要求“每秒就发 1 次请求”连续跑几个小时甚至几天。你别说这种低频压测还真不是没事找事。我第一次接到这个需求时也有点懵1 秒 1 次这还用压测直接手工在浏览器里点不就完了后来真做起来才发现里面门道不少。为什么有人要这么干用什么方式实现最稳怎么确认真的做到了每秒 1 次这些都是有讲究的。这篇文章就把我实际踩过的坑、验证过的方案完整写出来给同样遇到这类需求的朋友一个参考。先说这个任务是什么用 JMeter 构造一个稳定的、每秒恰好发出 1 次 HTTP 请求的测试场景并在此基础上做断言、看响应、出报告。它解决的问题是模拟真实系统里低频但持续性的调用行为验证服务在长时间低频请求下是否稳定接口有没有内存泄漏、连接未释放、慢请求堆积这类“慢性病”。适合谁看刚入门 JMeter 想搞明白定时器用法的测试新手以及遇到过“低频压测”需求但不知道怎么做最靠谱的同行。1. 先把场景说清楚每秒1次到底测的是什么1.1 高频压测做多了低频场景反而容易忽略做性能测试的人习惯性地会把注意力放在“能不能扛住高并发”上。线程数往大了调循环次数往多了拉看 TPS 曲线像过山车一样冲上去这才觉得像在做压测。但真实业务不全是高并发。很多系统的请求特征恰恰是“低频、长尾、持续”。比如物联网设备上报一台设备几分钟上报一次但设备数量可能有几万台单看每一台都是低频整体聚合起来才是压力。再比如定时任务触发的回调、客户端的心跳检测、第三方平台的轮询——这些都是典型的低频请求场景。用高频压测去测这类接口得出的结论往往失真。因为高频请求会放大 CPU 竞争、线程池排队这些因素掩盖了接口在稳定节奏下真正的问题。反过来如果只测低频很多人又觉得“这有什么好测的”于是干脆不测结果线上出了问题才发现是长期低频请求导致的连接泄漏或者内存缓慢增长。1.2 哪些业务场景需要“每秒1次”我整理了一下实际遇到过的需求大致有这么几类心跳/健康检查接口客户端或注册中心每隔固定时间探活比如 Nacos 客户端心跳。这种接口不需要高并发但必须保证长时间稳定响应。定时拉取/轮询接口比如前端轮询任务状态、后端定时拉取上游数据。频率通常不高但链路长、依赖多任何一个环节慢一点都会积累。消息推送后的回执确认推送服务发送后等待接收方回执频率由业务量决定一般不高。网关或防火墙的限流规则验证要验证“每秒只允许 1 个请求”的限流配置是否真的生效就得用精确的每秒 1 次去触发。稳定性长跑测试用固定低频持续跑 24 小时甚至 72 小时观察内存、句柄、连接池的变化。这是低频压测最有价值的地方。注意最后一条。很多团队做稳定性测试时喜欢让脚本跑得尽量快恨不得把机器打满。但真正的长稳测试反而不需要高并发——你要的是“持续、稳定、有规律的请求”这样才能观察出系统有没有资源缓慢泄漏的问题。低频长跑比高频长跑更容易暴露这类慢性问题因为高频时资源快速被占满问题很快就暴露了反而不符合真实场景的渐进式恶化。1.3 1秒1次不算压测这个误解该纠正了有人会杠每秒 1 次不叫压测叫“探活”。这其实是对压测的窄化理解。压测的本质是“用可控的请求压力验证系统在指定条件下是否满足预期”。压力是相对的——对一个只处理低频轮询的轻量服务来说每秒 1 次就是它的正常业务压力通过拉高频率去“压”它反而没有意义。换个角度看压测的粒度可以是频率也可以是总量。每秒 1 次、连续跑 86400 秒就是 86400 次请求的总量这对服务的长期稳定性就是个实实在在的压力测试。从我实际经验看低频压测真正考验的不是服务端扛并发的能力而是两点一是请求节奏的控制精度——能不能真的做到 1 秒 1 次而不是忽快忽慢二是长时间运行中的资源监控——比如你需要在压测的同时盯着 GC 日志、连接池活跃数、文件描述符数量。这两点恰恰是 JMeter 这类工具最容易被用错的地方。2. 实现每秒1次请求的两种主流方案2.1 方案一单线程 Constant Timer恒定定时器这是最直观、也最容易理解的方案把线程数设为 1在取样器前后加一个恒定定时器让每个请求之间固定间隔 1000 毫秒。具体配置方式是这样的添加线程组Thread Group线程数填 1Ramp-Up 填 0循环次数按你需要发送的总次数填。比如要跑 1 小时就是 3600 次。添加 HTTP 请求取样器填写协议、服务器地址、端口、路径、请求方式、参数。在 HTTP 请求下面添加定时器Constant Timer线程延迟Thread Delay填 1000 毫秒。运行测试。这里要说明一下 Constant Timer 的作用时机。JMeter 的定时器是在“取样器执行之前”生效的——每个取样器在发出请求前会先等待定时器设定的时间。所以你把 Constant Timer 放在 HTTP 请求的同级或子级它就会让这个请求每 1000 毫秒执行一次。循环次数怎么算很简单循环次数 期望跑的总秒数。跑 10 分钟就是 600 次跑 24 小时就是 86400 次。加上线程组里“循环次数”这个参数本身支持无限你也可以填“永远”然后用调度器里的持续时间来控制总时长。这个方案的优点配置简单逻辑清晰任何人一看就懂。缺点Constant Timer 是一个“死等”定时器它不关心上一次请求花了多长时间只负责在每次取样器执行前固定等待 1000 毫秒。这里有个细节很多人会忽略——如果你在一个线程组里放了多个取样器同一个 Constant Timer 会对每一个取样器都生效导致时间被成倍拉长。所以用这个方案时最好保持线程组里只有一个 HTTP 请求取样器或者用作用域仔细控制定时器只对目标取样器生效。2.2 方案二Constant Throughput Timer恒定吞吐量定时器如果说 Constant Timer 是个“笨办法”那 Constant Throughput Timer 就是更贴合“每秒 1 次”这个目标的方案。它不是固定等待而是动态计算需要等待的时间以保证整体吞吐量维持在设定值附近。配置方式在 HTTP 请求下添加定时器Constant Throughput Timer。Target Throughput 填 60.0单位是“每分钟请求数”。每秒 1 次 每分钟 60 次。Calculate Throughput based on 这一项选“this thread only”因为在我们的场景里只有一个线程。这里有三个选项需要理解this thread only只按照当前线程来维持吞吐量。适合单线程场景。all threads in current thread group按当前线程组所有线程的总吞吐来计算。all threads in current JVM按整个 JVM 里所有线程的总吞吐来计算。如果有多个线程组同时跑选这个可以让它们共同分摊目标吞吐。我为什么建议用 this thread only因为我们的目标就是“这一个线程每秒发 1 次”。如果选到其他两个选项JMeter 会根据总的活跃线程数动态调整等待时间一旦你后续加了线程节奏就会被重新计算反而不好控制。Constant Throughput Timer 的原理是基于吞吐量目标来倒推每一次请求间的等待时间。它内部会记录线程启动后的累计请求数和经过的时间然后计算出一个需要的延迟。好处是即便某个请求耗时较长后续请求也会自动微调保证单位时间内总请求数趋近目标值。这跟 Constant Timer 的区别我用一个表来说明对比项Constant TimerConstant Throughput Timer控制目标请求间隔固定单位时间请求数固定是否受请求耗时影响不受影响固定等待会根据耗时自动微调精度间隔精度高但实际吞吐会有波动吞吐精度高适合“每秒X次”的目标配置复杂度低中多线程场景适配需要小心作用域支持按线程组/JVM聚合计算2.3 两种方案怎么选我的建议很简单如果需求明确是“每秒 1 次、连续跑很久”优先用 Constant Throughput Timer。因为它直接面向吞吐量这个目标长时间运行时能自我修正节奏不会因为某次请求响应慢导致后面的请求被耽误。但是 Constant Timer 也不是一无是处。如果你要模拟的是“精确的固定间隔”比如每 1000 毫秒必须发一次不管上一次返回了没有那么 Constant Timer 更合适——因为它是硬等不受请求耗时影响间隔非常稳定。实际工作中我是怎么做的如果是几分钟的短测试随便选哪个都行差异不大。如果是几小时甚至几天的长跑测试我默认用 Constant Throughput Timer配合非 GUI 模式跑。后面我会详细说非 GUI 模式下怎么跑。这里还有一个进阶方案值得提一句如果你用 JMeter 插件管理器的 Arrivals Thread Group可以用“每秒到达 1 个请求”这种方式来建模概念上更像业界负载模型里的 Arrival Rate。它跟官方线程组的区别是官方线程组是“从线程池里取线程执行”Arrivals 是“按到达速率动态创建迭代”。不过 Arrivals Thread Group 对新手来说有点复杂而且依赖第三方插件我在只需要 1 个线程的场景下一般不引入避免增加环境的不确定因素。先把官方内置的两种方案玩明白绝大多数场景都够用了。3. 完整实操从新建测试计划到验证频率3.1 第一步创建线程组与HTTP请求打开 JMeter默认会有一个测试计划Test Plan。先给它起个名比如“每秒1次请求-长稳测试”。接着开始搭结构。右键测试计划 - 添加 - 线程用户 - 线程组。在线程组面板里这样填线程数1Ramp-Up 时间秒0循环次数填一个足够大的数或者勾选“永远”配合调度器的持续时间来控制总时长Ramp-Up 这里我必须强调一下单线程场景下 Ramp-Up 填 0 是对的因为只有一个线程不需要拉长启动时间。如果你填了 1 秒JMeter 会在 1 秒内启动这个线程但因为它只有 1 个实际启动几乎是瞬时的对结果没影响。但如果你线程数填了多个Ramp-Up 就很重要了——比如 10 个线程 Ramp-Up 填 10 秒那就是 1 秒启动一个线程。我们这里不需要所以填 0。然后添加 HTTP 请求取样器。在 Thread Group 上右键 - 添加 - 取样器 - HTTP 请求。这里要填的东西不用我啰嗦域名、端口、路径、方法、参数跟你在 Postman 里填的一样。需要注意一点如果你要测的是 HTTPS 接口JMeter 需要先处理证书问题这个不在本文范围内但遇到的时候要知道是证书问题而不是脚本问题。3.2 第二步配置定时器以我推荐的 Constant Throughput Timer 为例在 HTTP 请求上右键 - 添加 - 定时器 - Constant Throughput Timer。填两项Target Throughput60.0Calculate Throughput based onthis thread only就这么简单。跑起来之后理想状态下每秒 1 次请求会自动维持。如果你用的是 Constant Timer那就在 HTTP 请求上右键 - 添加 - 定时器 - Constant Timer把 Thread Delay 填 1000。这里插一句关于定时器作用域的提醒JMeter 定时器有个让人头疼的层级规则。如果你把定时器放在 HTTP 请求的子级它只对该请求生效如果放在线程组这一级它对该线程组下的所有取样器生效。所以当一个线程组里有多个 HTTP 请求时别把定时器放在线程组层级否则每个请求都会等待定时器的时间总耗时会被“取样器数量 × 定时器时间”放大。这是一个非常经典的坑我见过不少人在多请求场景下配了 Constant Timer结果吞吐量比预期低了好几倍查了半天才发现是定时器作用域搞的鬼。3.3 第三步验证请求频率是否准确配置完了怎么知道自己真的做到了每秒 1 次光凭感觉不行得用数据说话。最简单的方式添加一个“查看结果树”监听器跑一小会儿看请求时间戳。JMeter 在启动测试时每个请求都会有时间戳。如果你是在 GUI 模式跑直接看结果树里的请求列表两个相邻请求的启动时间差应该稳定在 1000 毫秒上下。但结果树监听器本身很耗资源长时间跑的时候不能开它。更专业的验证方式是用简单数据写入器Simple Data Writer把采样结果落盘然后检查日志文件的时间戳。具体操作右键线程组 - 添加 - 监听器 - 简单数据写入器文件名填一个 .jtl 后缀的文件。跑完用 Excel 或者命令行查看这个文件里面每一行是一条采样记录有 timeStamp 字段也就是请求启动时的毫秒时间戳。把相邻两行的时间戳相减得到的应该就是 1000 毫秒左右。如果偏差超过 100 毫秒说明你的节奏有问题需要回去检查定时器配置。我再分享一个自己常用的土办法写一个 JSR223 后置处理器在每个请求结束后用 System.currentTimeMillis() 打印当前时间然后在日志里看相邻两个请求的时间差。这个方法在 GUI 模式下很直观适合刚开始调试脚本时用。等脚本磨合成型了再用简单数据写入器做正式记录。3.4 非GUI模式跑起来更省资源压测跑到最后一定要用非 GUI 模式。原因很简单GUI 模式本身会消耗大量内存和 CPU尤其是在开着各种监听器结果树、聚合报告、图形结果的情况下。你用一个占着资源的工具去测性能测出来的数据能准吗非 GUI 模式启动命令长这样jmeter -n -t /path/to/test.jmx -l /path/to/results.jtl -j /path/to/jmeter.log参数说明-n非 GUI 模式-t指定测试脚本文件-l指定结果日志文件-j指定 JMeter 运行日志文件如果你配置了调度器的持续时间测试会在时间到后自动结束。如果没有等所有循环跑完也会结束。长稳测试建议在脚本里配好持续时间这样不用人守着。在 Linux 服务器上跑长稳测试我还习惯用 nohup 放到后台执行nohup jmeter -n -t plan.jmx -l result.jtl -j run.log /dev/null 21 跑完之后用 tail -f run.log 可以实时观察执行进度看到“end of run”字样就说明跑完了。这里有个细节JTL 文件会越写越大长跑 24 小时的话可能产生几百 MB 的数据。建议在测试计划里配置结果采样策略只记录必要的信息。我一般用 -J 参数按需开启字段比如记录线程数、时间戳但关闭响应体等大字段减少落盘数据量。4. 压测中的灵魂断言、响应查看与报告导出4.1 JSR223 / Beanshell 断言实战频率控制好了请求发出去了怎么知道每次请求到底成功没有只看 HTTP 状态码 200 远远不够。很多接口在业务层返回的 HTTP 200 但 body 里带着错误码这时候就需要断言。JMeter 自带的“响应断言”可以检查响应文本是否包含某个字符串但它能力有限——一旦需要做逻辑判断比如同时校验多个字段、根据时间做条件判断、取出某个值再跟预期比较就得写脚本了。JMeter 支持 Beanshell 和 JSR223 两种脚本方式。我的建议是优先用 JSR223 Groovy不要用 Beanshell。原因很简单Beanshell 在 JMeter 中的执行效率比较低高频场景下会拖慢测试节奏而且 Groovy 语法更现代、更好写。虽然我们这里才每秒 1 次Beanshell 性能影响不大但养成好用 JSR223 的习惯总是对的。一个典型的 JSR223 断言脚本长这样放在 HTTP 请求下的 JSR223 断言里// 获取响应内容 def response prev.getResponseDataAsString() def status prev.getResponseCode() // 1. 状态码必须是200 if (status ! 200) { AssertionResult.setFailure(true) AssertionResult.setFailureMessage(状态码异常: status) return } // 2. 业务code必须是0 def json new groovy.json.JsonSlurper().parseText(response) if (json.code ! 0) { AssertionResult.setFailure(true) AssertionResult.setFailureMessage(业务错误: code json.code , msg json.msg) return } // 3. 响应时间不能超过3秒 if (prev.getTime() 3000) { AssertionResult.setFailure(true) AssertionResult.setFailureMessage(响应超时: prev.getTime() ms) }注意脚本里用的 prev 对象它是 SampleResult 的引用通过它可以拿到响应数据、状态码、耗时等。AssertionResult 是断言结果的引用调用 setFailure 即可标记失败。我还用了一个实战技巧把从响应里解析出来的关键字段保存成 JMeter 变量供后续请求使用。比如从登录接口响应里取出 token存在 vars 里def json new groovy.json.JsonSlurper().parseText(prev.getResponseDataAsString()) vars.put(token, json.data.token)之后的请求里就可以用 ${token} 引用。这在构造有依赖关系的接口链路时非常有用。4.2 压测过程中实时查看响应内容很多人问我在 Linux 上跑 JMeter 压测怎么实时看接口返回了什么GUI 模式当然可以开结果树但服务器上通常没有图形界面而且开着结果树会影响压测结果。我的做法有三个层次第一层临时查看用“视图结果树”只在小范围、短时间调试时开确认脚本格式和请求参数没问题后立刻关掉。第二层把完整响应数据写入文件。在 HTTP 请求下添加一个“保存响应到文件”后置处理器配置好保存路径和文件名前缀。这样每次请求的响应都会落盘压测完直接去看文件内容。文件数量会随着请求数量增长所以这个方案适合短时间调试不适合长测。第三层在 JSR223 后置处理器里做条件保存。比如只把断言失败或响应异常的请求内容保存下来def body prev.getResponseDataAsString() if (prev.getResponseCode() ! 200 || prev.getTime() 3000) { def f new File(/tmp/error_ System.currentTimeMillis() .txt) f.text body }这个做法的好处是只保留异常样本文件量很小。跑完长测后直接 ls /tmp/error_*.txt 就能看到所有异常请求的响应内容排查问题效率极高。脚本里注意加个时间戳后缀避免多个请求写到同一个文件互相覆盖。4.3 一条命令生成HTML测试报告JMeter 从 3.0 开始支持直接生成 HTML 报告这是个被低估的功能。很多人压测完了只知道看 .jtl 文件里的原始数据其实 JMeter 自带的报告生成器能产出一套完整的可视化报告包含吞吐量曲线、响应时间分布、错误率、活跃线程数等图表特别适合用来做团队汇报。前提条件跑测试的时候必须记录足够多的数据字段否则报告里的很多图表是空的。建议用这样的命令启动测试jmeter -n -t plan.jmx -l result.jtl \ -Jjmeter.save.saveservice.response_datafalse \ -Jjmeter.save.saveservice.samplerDatafalse \ -Jjmeter.save.saveservice.requestHeadersfalse \ -Jjmeter.save.saveservice.responseHeadersfalse \ -Jjmeter.save.saveservice.thread_countstrue \ -Jjmeter.save.saveservice.timestamptrue简单说像响应体、请求体这种体积大的字段别存不然 .jtl 文件会爆炸线程数、时间戳这种报告必须的字段一定要存。跑完之后生成报告jmeter -g result.jtl -o /path/to/report/dir-g 指定结果文件-o 指定输出目录。输出目录必须不存在或者是空目录否则会报错。这是 JMeter 的一个不太友好的设定我第一次用就被它坑过。生成的 index.html 用浏览器打开就能看里面有很多图表区域。我个人最常用的是这三个吞吐量随时间变化图验证每秒请求数是否稳定在 1 左右。响应时间百分位图看 P90、P95、P99 的响应时间有没有突发尖峰。活跃线程数图确认线程数量在整个测试期间没有异常波动。5. 常见问题与排查技巧实录5.1 频率不准确的几大原因我在实际测试中遇到过很多次“明明配了 1000 毫秒结果实际间隔不是 1 秒”的情况。归结起来原因就这么几个第一GUI 模式对节奏的影响最大。JMeter 本身需要分配资源去处理界面刷新和监听器数据展示每一次取样器执行完监听器都要更新界面这会挤压定时器的执行精度。所以为什么我一直强调非 GUI 模式——不只是为了省资源更是为了保证定时器按预期工作。第二脚本里存在额外的处理逻辑。如果你加了响应断言、JSR223 后置处理、正则表达式提取器之类的组件这些组件的执行时间会计入取样器的总时间。而 Constant Throughput Timer 是通过控制吞吐量来反向调整等待时间的它会把所有额外处理时间都算进去然后压缩定时等待时间导致整体的请求间隔被调整。这不是 bug是它的设计逻辑你要理解它才会用对它。第三目标吞吐量设置错误。每秒 1 次 60 次/分钟这个换算很多人会搞错。如果你填了 1.0那就变成每分钟 1 次也就是 60 秒 1 次完全混了。我在项目里见过同事把 60 填成 600压出来的流量直接翻了 10 倍。这个错误很常见因为 Constant Throughput Timer 的单位是每分钟不是每秒。第四JVM 环境问题。比如 GC 停顿会导致请求间隔忽大忽小尤其是在堆内存配置不合理的情况下。长稳测试前确认 JMeter 自己有足够的内存启动脚本里给 HEAP 参数留够空间。JMeter 默认的堆内存只有 1GB长跑大量采样记录时很容易触发 GC。建议修改 bin/jmeter 脚本里的 HEAP-Xms1g -Xmx2g 或者更大。5.2 定时器之间的区别与误用JMeter 的定时器家族很庞大除了本文提到的 Constant Timer 和 Constant Throughput Timer还有高斯随机定时器、均匀随机定时器、同步定时器Synchronizing Timer用来制造瞬间并发、BeanShell 定时器、JSR223 定时器等。新手最容易混淆的是这几个Constant Timer固定等待不关心前面发生了什么。Gaussian Random Timer在指定均值和标准差之间随机等待。比如均值 1000ms、标准差 100ms那等待时间大致在 900~1100ms 之间浮动。用于模拟更真实的人类操作节奏。Uniform Random Timer类似高斯但随机分布是均匀的。Synchronizing Timer让多个线程在某个点集合然后同时释放。这个是用来制造并发峰的跟“每秒 1 次”的场景完全相反。如果你要模拟“真实用户每隔一秒操作一次”这种场景用 Gaussian Random Timer 比 Constant Timer 更贴近现实因为真实用户的间隔不可能是机器般精确的。但如果你的目标是“严格每秒 1 次”比如验证限流规则那就必须用 Constant Timer 或 Constant Throughput Timer不能引入随机性。还有一个容易踩的坑同步定时器出现在线程组里时会让所有线程卡在集合点互相等待如果你一共就 1 个线程它也会等——等到超时为止。有人把同步定时器从之前的并发测试脚本里复制过来忘了删结果压测一直卡住请求发不出去。排查时先检查线程组下面所有组件尤其是这种“看不见”的定时器。5.3 Linux下压测的几个坑服务器上跑压测有一些跟 Windows 上不一样的问题。我捡几个典型的说。第一个是时间同步。如果你的测试脚本依赖系统时间来做断言或记录那压测机和被压测的服务器之间要做好时间同步否则你对比两边日志时会对不上。第二个是文件句柄限制。跑长稳测试时JMeter 每发一次请求就要建立一个连接取决于你用的是否是 keep-alive如果被压测服务的连接不释放JMeter 侧的文件描述符会持续增长。Linux 默认的 ulimit -n 可能只有 1024长跑之后 JMeter 会报 “Too many open files”。跑之前先 ulimit -n 65535 或者更大。第三个是 nohup 与 jmeter 进程的关系。在 Linux 上用 nohup 启动 JMeter 后如果你直接关掉终端进程可能会被挂断信号杀掉。虽然 nohup 理论上会忽略挂断信号但某些环境下还是会有问题。更稳妥的做法是用 setsid 或者 screen/tmux 跑尤其是长时间无人值守的测试。第四个是查看响应内容时别用“查看结果树”。服务器上没有图形界面你开了结果树它要么没法显示要么会占用大量内存。用前面提到的“保存响应到文件”或者 JSR223 条件保存更实用。5.4 遇到问题怎么办排查思路压测中的问题五花八门但排查思路大致是固定的。我自己习惯按这个顺序来第一步先确认 JMeter 这一侧没有锅。看 jmeter.log 有没有报错看取样器的响应码和响应信息。很多“压测不行”的问题本质上是脚本的问题——参数没传对、鉴权没过、请求头少了字段。第二步确认节奏正确。用简单数据写入器的 .jtl 时间戳做检查相邻请求间隔是否稳定。如果节奏乱了回查定时器配置和作用域。第三步确认被压服务没被打挂。看服务端日志、监控指标、连接数、GC 情况。如果是长跑测试重点看内存曲线是否随时间缓慢爬升——那才是低频长测最想抓的问题。第四步确认网络链路正常。压测机和目标服务之间有没有防火墙、负载均衡、限流组件拦截。尤其注意很多网关默认会对高频请求做限流但低频请求也可能被一些“慢速攻击防护”策略拦截因为它觉得你“频率太低像扫描”。这个我在一个客户现场踩过坑1 秒 1 次的心跳请求被防护设备识别成慢速扫描给拦了对方还以为是我们压测代码写错了。6. 个人体会与小技巧做了几年性能测试我自己的体会是低频压测比高频压测更需要耐心也更考验细节。高频压测出了问题几分钟就能看出来低频长测出了问题可能要在几小时甚至几天后才暴露。所以跑低频长测之前一定要把脚本、定时器、断言、日志策略全部打磨清楚宁可先跑 10 分钟短的确认无误再上完整的时长。我见过有人直接拿一个没验证过的脚本跑了 24 小时第二天醒来发现请求路径都是错的整个测试白做——这种事一次就够长了记性。最后分享一个小技巧JMeter 跑低频长测时不要在脚本里放太多监听器。监听器每处理一条采样数据都会消耗资源低频场景下虽然流量不大但如果监听器写文件过于频繁磁盘 IO 也可能成为瓶颈。我一般只保留简单数据写入器或者干脆去掉监听器只用 jmeter.properties 里的内置 summary 输出。summary 每隔一段时间会在 jmeter.log 里打印一次汇总包含当前请求数、错误数、吞吐量等用 tail -f 盯这个就够了。再补一句如果你要测的目标是“验证接口在低频请求下的响应时间稳定性”除了看平均响应时间建议重点看 P99 和响应时间的方差。低频请求的场景里响应时间突然从 200ms 跳到 5 秒往往是连接池重建、缓存过期、懒加载这类问题的信号。把响应时间变化曲线和 GC 日志放在一起看能定位到很多有意思的问题。这就是我在这类“每秒 1 次”压测任务里的全部实践经验。方案不一定是最优的但都是我验证过、在项目里真正跑过的路子。大家在自己环境里跑的时候遇到什么奇怪的问题欢迎交流。毕竟压测这东西纸上谈兵没用只有自己跑过的数据才最有说服力。
返回列表