Concurrency Thread Group详解
这个线程组是 JMeter 标准线程组(如 Thread Group)的一个强大替代品,特别设计用于实现更精细、更稳定、更符合真实场景的并发用户模型。它属于 JMeter 插件的一部分(通常通过 Custom Thread Groups 插件安装),极大地扩展了 JMeter 的负载配置能力。
核心思想与目的
Concurrency Thread Group 的核心是专注于 维持指定的并发用户数(并发级别),而不是简单地启动固定数量的线程去做尽可能多的迭代。它通过动态调整实际运行的线程数和线程迭代间的思考时间来主动维持目标并发量。
这与标准线程组有本质区别:
-
标准 Thread Group:
- 配置固定数量的线程。
- 每个线程尽可能快地执行其测试计划(取样器),每次执行称为一个“迭代”。
- 并发用户数会受到服务器响应时间(Sampler 执行时间)的变化和线程迭代间是否有设置思考时间的影响,并发量会波动。
- 你控制的是线程数,但不是直接控制并发的瞬时活动用户数。
-
Concurrency Thread Group:
- 配置目标并发用户数(例如,100个并发用户)。
- 线程组会根据设定的规则(启动速率、递增时间等)朝目标并发数靠近。
- 它会动态计算需要运行多少个线程,并调整这些线程执行迭代之间的思考时间(
pacing
)来确保在任意时刻(或平均意义上)接近目标并发数。服务器响应变慢时,它可能会启动更多线程以达到并发目标;服务器响应变快时,它可能会启动更少线程或增加思考时间(pace)来避免超过并发目标。 - 你控制的是并发级别的目标值。
主要功能与优势
- 真正的并发控制: 最核心的优势。允许你精确指定希望保持的活动(处理请求)用户数。这对于需要模拟特定恒定压力的场景(如负载测试、压力测试)至关重要。
- 自动线程调整: 插件自动管理活动线程的数量。不再是“启动后不管”,而是根据目标并发量和服务器响应动态调整线程池大小。类似于云负载的弹性伸缩能力。
- 步进式/平滑加压: 可以定义:
- 启动批次/步数: 分几个批次达到目标并发。
- 启动线程数/每次增加并发量: 每个批次启动多少个新线程或达到多少并发。
- 启动时间/上升时间: 每个加压步骤持续的时间。
- 递增间隔: 批次之间的间隔时间。
- Hold 负载时间: 达到目标并发后,持续负载多长时间。
- 关闭时间/下降时间: 测试结束时,负载下降(线程停止)的时间。
- 这种配置允许非常灵活地模拟真实用户的逐步进入和退出系统。
- 与正常 Thread Group 参数的兼容性: 仍然可以设置“循环次数”或“调度持续时间”,在达到这些限制或 Hold 时间结束时停止。
关键配置参数详解
在 Concurrency Thread Group 的配置界面中,你会看到以下重要参数:
- 目标并发量: 希望达到和维持的目标并发用户数(虚拟用户)。
- 启动时间 / 上升时间: 等待多长时间达到目标并发。
- 递增间隔: 每次增加多少用户?(并发的递增不是连续不断的,而是按间隔来增加,比如每10s并发加10,直到目标并发)
- Hold 负载时间 / Hold Target Rate Time: 达到目标并发后,持续负载多长时间。
- 关闭时间 / 下降时间: 负载从目标并发降为0所需的时间。
- 线程迭代次数限制: 类似于标准线程组的“循环次数”。可以设置为“无限”或用计数器限制每个线程最多运行多少次。
- 日志线程状态到文件: 方便调试线程启动停止逻辑。
- 停止/结束条件:
- 在采样器错误后关闭: 如果请求失败则终止该线程(常用于失败后不重试的场景)。
- 限制总运行时间: 设置整个测试运行的总时长(秒)。
- 停止线程: 停止测试时如何处理活动线程(立刻停止、优雅停止等)。
工作流程简述
- 初始化: JMeter 启动时,Concurrency Thread Group 根据配置开始工作。
- 攀升阶段:
- 按照设定的“启动时间”和“递增间隔”,分批次增加并发量(达到目标并发用户数)。
- 每个间隔,按需启动新的线程(或复用线程池中的空闲线程)来增加活动用户数。插件会自动计算如何以设定的时间间隔达到目标并发。
- 稳定维持阶段:
- 当达到目标并发量后,进入“Hold 负载时间”。
- 插件动态工作:
- 监测计算当前的实时活动用户数。
- 如果活动用户数低于目标:
- 尝试启动新线程(如果达到总线程数上限则等待)。
- 可能减少现有线程的迭代间思考时间(
pacing time
),让它们更快地发出下一个请求。
- 如果活动用户数高于目标:
- 尝试停止一些空闲线程(如果允许)。
- 增加现有线程的迭代间思考时间(
pacing time
),强迫它们慢点发出下一个请求,降低频率。
- 目标是让蓝色的活动用户线尽可能地贴近黄色的目标并发线。
- 下降阶段:
- “Hold 负载时间”结束后(或者达到设定的总运行时间或迭代次数限制),开始“关闭时间”。
- 按照设定的时间逐步减少目标并发量(通常是线性下降到0)。
- 通知正在运行的线程完成当前迭代后停止。插件停止启动新请求。
- 结束: 所有线程停止,测试结束。
使用场景示例
假设你要模拟一个在线购物的负载测试:
- 目标: 保持 500 个用户同时浏览和搜索商品。
- 配置:
- 目标并发量:
500
- 启动时间:
300
秒 (5分钟, 模拟用户慢慢登录) - 递增间隔:
每30s增加 50
(30秒为1个批次,每次并发增加50) - Hold 负载时间:
600
秒 (10分钟, 压力峰值期) - 关闭时间:
120
秒 (2分钟, 用户慢慢退出) - 循环次数:
无限
- 目标并发量:
在这个例子中,负载模型是这样的:
- 第 0-300 秒:并发量每 30 秒增加 50,最终在第 300 秒(5分钟)结束时达到 500 并发。
- 第 300-900 秒:插件努力维持稳定的 500 用户并发。服务器慢,它就多启动点线程;服务器快,它就少启动线程或增加思考时间。
- 第 900-1020 秒:并发量从500目标开始以平均每分钟 250 用户的速率线性下降,在 1020秒结束时下降为零。
- 总测试时间:1020秒(17分钟)。
优点总结
- 精确并发控制: 直接设定并维持期望的“活动用户”数量。
- 稳定负载: 通过动态调整,更好地维护目标负载水平,减少因响应时间波动导致的负载抖动。
- 更真实的用户行为模拟: 体现用户逐步进入系统、稳定使用、逐步退出的过程。
- 更高的资源利用率: 避免因等待、思考时间过多而造成线程资源的浪费,或者在响应快时产生过高的非必要负载。
- 符合现代负载测试模型: 更接近于 LoadRunner、CloudTest (Taurus/Gatling) 等工具中的并发模型。
注意事项与使用建议
- 安装插件: 必须先通过 JMeter Plugins Manager 安装
Custom Thread Groups
插件。 - 理解“维持”而非“启动”: 你设定的是并发目标值,插件管理实际线程数来实现这个目标。
- 影响 Thread Pool Size: 这个线程组会主动创建/销毁线程以适应目标并发。这本身是有开销的。为避免过多开销,设一个合理的初始线程池上限(虽然插件会动态管理,但物理资源总有限制)。
- 思考时间(Think Time): 在测试计划中定义的思考时间仍然重要!插件通常是在你设置的 恒定思考时间或随机思考时间 基础上再动态调整一个
pacing time
(Ramp-up Limit
),以确保最终的请求速率和活动用户数达到目标。强烈建议使用 Random Timer 或 Gaussian Random Timer 来模拟真实的用户操作间隔。 - 复杂性: 比标准线程组配置稍复杂一些。理解参数含义很重要。
- 可视化: 强烈建议配合
jp@gc - Active Threads Over Time
监听器进行监控。它可以实时绘制目标并发线(黄色)和实际活动线程线(蓝色),让你清晰看到插件是否有效维持了并发目标。 - 并非万能: 对于需要精确控制每个线程行为序列或复杂时序的场景(如固定 RPS 请求),可能
Ultimate Thread Group
或Constant Throughput Timer
更合适。但它依然是精确模拟用户并发级别的黄金标准线程组。
总结
JMeter 的 Concurrency Thread Group 是进行高质量负载测试、压力测试、容量规划的必备工具。它突破了传统线程组只控制线程启动的局限,通过动态管理线程池和工作负载(pacing),使得用户能够精确地配置和稳定维持所期望的并发用户负载水平。它尤其适合需要长时间恒定压力或平滑加减载曲线的场景。掌握其配置和工作原理,可以极大地提升你的负载测试的逼真度和准确性。