JMeter原生不支持MongoDB事务,因其内置插件已废弃且无法维持ClientSession生命周期;必须用JSR223 Sampler配合MongoDB Java Driver 4.x+手动管理session的start/commit/abort全流程。

JMeter 原生不支持 MongoDB 事务(session.startTransaction()、session.commitTransaction()),官方早在 3.0 版本就废弃了 MongoDB Source Config 和 MongoDB Script 插件,且这些插件根本不处理会话生命周期和事务上下文——直接用它们压测事务,结果全是假阳性或连接泄漏。
为什么不能用 JMeter 内置 MongoDB 插件测事务
那些标着 (DEPRECATED) 的 MongoDB 元件本质是单命令直连模式:每次取样器执行都新建/复用一个无状态连接,无法维持 ClientSession 实例,更没法跨多个取样器传递 session 对象。事务必须在同一个 ClientSession 内完成 begin → ops → commit/abort 全流程,而 JMeter GUI 中的“MongoDB Script”只允许写一段 JS 字符串,无法控制 Java 驱动层的 session 管理逻辑。
- 你写的
db.collection.insertOne(...)会被当作普通操作执行,不进事务 - 即使脚本里调用
session.startTransaction(),下一次取样器运行时 session 已销毁 - 驱动版本混用(如塞入
mongo-java-driver-3.8.2.jar)会导致NoClassDefFoundError或静默失败 - JMeter 启动时若未清掉旧驱动(如
mongo-java-driver-2.11.3.jar),类加载冲突概率极高
正确做法:用 JSR223 + 官方 Java 驱动手动编码事务
必须绕过所有 MongoDB 相关 GUI 插件,改用 JSR223 Sampler + groovy 脚本,直接调用 MongoDB Java Driver 4.x+ 的同步 API。关键点是复用 MongoClient 和按需创建/关闭 ClientSession。
- 把
mongodb-driver-sync-4.11.2.jar(或更高兼容版)丢进$JMETER_HOME/lib/ext/,重启 JMeter - 在线程组级用
setUp Thread Group初始化MongoClient并存入props:import com.mongodb.client.MongoClients import com.mongodb.client.MongoClient def client = MongoClients.create("mongodb://localhost:27017") props.put("mongoClient", client) - 在主线程组的
JSR223 Sampler中获取 client、开启 session、执行多文档操作、显式 commit:
import com.mongodb.client.ClientSession
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import org.bson.Document
import static com.mongodb.client.model.Filters.*
import static com.mongodb.client.model.Updates.*
<p>def client = props.get("mongoClient")
def database = client.getDatabase("testdb")
def collection = database.getCollection("orders")</p><p>// 必须显式创建 session
ClientSession session = client.startSession()
try {
session.startTransaction()</p><pre class="brush:php;toolbar:false;">collection.insertOne(session, new Document("order_id", java.util.UUID.randomUUID().toString()).append("status", "created"))
collection.updateOne(session, eq("order_id", "tmp_123"), set("status", "processing"))
session.commitTransaction()} catch (Exception e) { session.abortTransaction() throw e } finally { session.close() }
压力与极限测试的关键配置陷阱
事务压测不是堆线程数就行。MongoDB 事务有隐式资源上限,JMeter 配置稍错就会触发锁等待、超时或连接耗尽。
-
线程数不宜超过 MongoDB 的maxConns(默认 65536,但受 ulimit 限制),建议从 50 起步,观察db.currentOp({secs_running: {$gt: 1}})是否堆积长事务 -
Ramp-Up Period必须 > 0(比如设为 60 秒),避免瞬间开启上千 session 导致 WiredTiger cache 暴涨、OOM - 务必勾选线程组的
Same user on each iteration,否则每次循环都会新建 session,快速占满连接池 - 在
tearDown Thread Group里显式关闭 client:def client = props.get("mongoClient") if (client != null) client.close() - 监控项不能只看 JMeter 的
90% Line,要同时查 MongoDB 日志里的transaction took longer than slow transaction threshold和WT_ROLLBACK错误
真正难的是让每个事务既真实又可控:插入、更新、删除跨集合操作得封装成原子块,异常路径必须 abort,session 生命周期必须和线程绑定——这些逻辑全得手写进 groovy,没法靠点点点完成。漏掉 session.close() 或没包 try/catch/finally,跑 10 分钟后连接数就卡死在 1000+。











