Karate Gatling压测时如何将API响应存储至文件
Karate Gatling压测场景下API响应数据持久化落盘实现方案
核心设计思路
将原本串联执行的“创建预订-更新预订”全链路流程拆分为两个独立压测环节,第一环节单独运行创建预订接口,把所有成功返回的bookingId全量持久化到本地文件,第二环节直接读取文件存储的合法ID,独立发起更新/取消请求。通过两个环节的性能数据拆分,就能准确定位瓶颈是来自被测API服务侧,还是Karate框架的流程执行开销。
实现步骤
1. 拆分独立的压测feature文件
新建一个仅包含创建预订调用逻辑的feature文件,去掉和更新预订相关的步骤,专门用于第一阶段的ID收集压测:
# 文件路径:classpath:createBookingOnly.feature Feature: 独立创建预订场景-用于收集bookingId Background: * url '你的被测API服务地址' Scenario: 调用创建预订接口 Given request { 在此处填入你原有的创建接口请求体参数 } When post '/booking' Then status 200 * def bookingId = response.bookingId
2. 实现线程安全的文件写入工具
由于压测场景下是多虚拟用户并发执行,直接做文件写入会出现并发冲突、内容覆盖的问题,需要基于Java NIO实现轻量、线程安全的追加写逻辑,和feature文件同路径下新建filePersist.js:
function appendLineToFile(filePath, content) { // 复用全局类对象作为同步锁,避免并发写入冲突 var syncLock = Java.type('com.intuit.karate.JavaScript').class; var Files = Java.type('java.nio.file.Files'); var Paths = Java.type('java.nio.file.Paths'); var StandardOpenOption = Java.type('java.nio.file.StandardOpenOption'); // 加同步块保证同一时刻仅一个线程执行文件写入 synchronized(syncLock) { Files.write( Paths.get(filePath), (content + System.lineSeparator()).getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND, StandardOpenOption.WRITE ); } }
在刚才的创建预订feature中,拿到bookingId之后调用工具方法,把内容追加写入到指定路径的文件:
# 接Scenario中拿到bookingId的步骤,追加写入逻辑 * call read('classpath:filePersist.js') * eval appendLineToFile('./收集的有效bookingId.txt', bookingId)
3. 调整Gatling压测仿真配置
修改原有压测脚本,第一阶段直接指向独立的创建预订feature,按照原有的1000用户1秒增压的配置执行:
val collectScenario = scenario("独立创建预订-收集bookingId") .exec(karateFeature("classpath:createBookingOnly.feature")) setUp( collectScenario.inject(rampUsers(1000).during(1.seconds)) )
压测执行完成后,指定路径下的收集的有效bookingId.txt会按行存储所有接口返回的合法预订ID,可直接用于后续更新/取消接口的压测。
压测环节拆分与瓶颈定位
完成ID收集后,可独立开展两个接口的单环节压测,拆分总耗时定位问题:
- 单独压测创建预订接口:记录该接口的响应时间、吞吐量数据,对比被测服务侧的处理日志,判断创建环节的性能是否符合预期
- 单独压测更新/取消预订接口:读取存储文件中的bookingId作为入参发起请求,记录该环节的性能数据
- 若单环节压测下两个接口的吞吐量均远高于原串联场景的总吞吐量,说明瓶颈来自Karate的多feature串联调用开销;若单环节压测下接口吞吐量本身不达标,说明瓶颈来自被测服务侧的业务处理逻辑。
注意事项
- 文件写入动作需放在接口响应校验通过之后执行,避免将IO操作的耗时算到接口响应时间中,干扰压测结果判断
- 1000用户量级的压测场景下,使用Java NIO的追加写方式完全不会产生明显的性能开销,无需额外优化;若后续压测量级达到万级以上,可将ID暂存在虚拟用户内存中,待场景执行结束后统一落盘
- 不要通过解析压测日志提取bookingId,日志格式存在动态变化的可能,主动落盘的方式能保证全量ID的完整性和可解析性
内容的提问来源于stack exchange,提问作者Dilleswar
相关产品推荐
相关产品推荐

