Gatling 发送 multipart/form-data + XML 需手动构造带唯一 boundary 的请求体,XML 作为 form-data part 且含正确 Content-Disposition;rampUsersPerSec 不等于实际并发数,因上传耗时导致并发累积,应优先用 rampConcurrentUsers 控制真实连接数;需动态生成签名、唯一文件名并校验响应 XML 结构,避免静态脚本失真。

如何用 Gatling 发送 multipart/form-data + XML 文件
Gatling 默认不直接支持 multipart 文件上传(尤其是带 XML 内容的),必须手动构造请求体并设置正确 Content-Type 和边界(boundary)。常见错误是直接用 bodyFile 或 StringBody 发送 XML,结果服务端收不到文件字段、解析失败或返回 400 Bad Request。
- XML 必须作为
form-data的一个 part,不能裸发;否则多数后端(如 Spring Boot@RequestPart)会拒绝 - 需显式指定
Content-Disposition: form-data; name="xmlFile"; filename="data.xml" - 必须生成唯一 boundary,并在
Content-Type头和请求体中严格一致 - 推荐使用
RawHttpBody+ Scala 字符串拼接,避免依赖外部库(Gatling 3.10+ 不内置 multipart 工具类)
val xmlContent = "" val boundary = "----WebKitFormBoundary" + java.util.UUID.randomUUID().toString.replace("-", "") 123 - book
val multipartBody = s"""--${boundary} Content-Disposition: form-data; name="xmlFile"; filename="order.xml" Content-Type: application/xml
${xmlContent} --${boundary}-- """
val httpProtocol = http .baseUrl("https://www.php.cn/link/710ba53b0d353329706ee1bedf4b9b39") .header("Content-Type", s"multipart/form-data; boundary=${boundary}")
val scn = scenario("XML upload") .exec(http("upload-xml") .post("/v1/orders/upload") .body(RawHttpBody(multipartBody)) .check(status.is(200)) )
为什么 rampUsersPerSec 不等于实际上传并发数
XML 上传是长耗时操作(尤其大文件或后端校验强),rampUsersPerSec 控制的是“每秒发起新会话的速率”,不是“同时活跃连接数”。若单次上传平均耗时 5 秒,rampUsersPerSec(20) 实际稳定并发约 100,而非 20 —— 这容易导致误判容量瓶颈。
- 用
concurrentUsers更直观:比如rampConcurrentUsers(50) to (200) during (5 minutes)明确控制并发连接上限 - 务必在
setUp中加.maxDuration,防止因上传慢导致测试无限延长 - 监控 Gatling 报告里的
active users曲线,和后端Thread Count对齐,才能定位是网络、IO 还是线程池堵住
真实场景下必须绕开的三个坑
生产环境 XML 上传常伴随鉴权、签名、分片或回调,Gatling 脚本若只发静态 body,压测结果完全失真。
-
动态签名失效:XML 内容含时间戳或 hash,需用
session变量实时计算,不能写死StringBody -
文件名/ID 冲突:多个用户并发上传同名 XML,可能触发后端幂等拦截 → 用
${Integer.toString(session.userId)}或java.util.UUID.randomUUID()注入唯一标识 -
大 XML 内存溢出:单次上传 10MB XML,100 并发即占 1GB 堆内存 → 改用
ElFileBody(需自定义)或拆成小文件流式上传(Gatling 原生不支持流,得换 JMeter)
如何验证后端是否真的收到了完整 XML
光看 HTTP 状态码 200 不够。XML 解析失败时,有些服务仍返回 200 + 错误 JSON body,Gatling 默认不检查响应内容。
- 加
.check(bodyString.saveAs("responseBody"))提取响应体,再用正则或 XPath 验证关键字段 - 对 XML 响应做结构校验:
check(xpath("//result/status").is("success")) - 开启 Gatling 日志调试:
gatling.sh -rf /path/to/results -s YourSimulation -sf /path/to/simulations -rd "XML Upload Debug",查request.log确认原始 body 是否含预期 boundary 和 XML 内容
真实高并发 XML 上传的难点不在 Gatling 怎么发,而在于你能否让每次请求都像真实客户端一样“活”起来:带签名、有唯一 ID、能处理重定向、失败后自动重试 —— 这些逻辑一旦硬编码进脚本,维护成本就上去了。别省那几行 Scala。










