You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vert.x HttpClient在30K RPM、100KB负载下内存飙升致崩溃问题

Vert.x HttpClient高并发测试内存飙升崩溃问题排查与修复

问题根源

  • 未完全消费异步请求结果:你的代码仅处理了request成功的分支,既没有处理request创建失败的场景,也没有订阅send(payload)后的响应或失败回调。Vert.x的异步请求对象如果没有被完整处理(即未完成整个生命周期的回调绑定),会导致请求上下文、payload等资源无法被GC回收,持续占用内存直至溢出。
  • 大Payload的低效生成:每次请求都重复将100KB负载转为Base64再转字节,会生成大量临时字符串和字节数组对象,且这些对象无法被及时回收,加剧内存压力。
  • 无请求并发限制:30K RPM(约500QPS)的请求量下,平均响应时间71ms意味着同时会存在约35个活跃请求,但如果没有设置HttpClient的连接池和等待队列上限,当请求堆积时,内存中会留存大量待处理的请求实例和Payload数据。

修复代码

// 提前预解码并复用Payload,避免重复转换
String base64PayloadStr = "你的Base64负载字符串";
Buffer reusablePayload = Buffer.buffer(Base64.getDecoder().decode(base64PayloadStr));

// 配置HttpClient的并发控制参数,根据系统资源调整
HttpClientOptions clientOptions = new HttpClientOptions()
        .setMaxPoolSize(1000) // 最大活跃连接数
        .setMaxWaitQueueSize(2000); // 最大等待队列长度
HttpClient httpClient = vertx.createHttpClient(clientOptions);

httpClient.request(requestOpts)
        .onSuccess(request -> {
            request.send(reusablePayload)
                    // 处理响应,必须订阅以释放资源
                    .onSuccess(response -> {
                        // 读取响应体(若无需处理也需调用,确保资源释放)
                        response.body().onSuccess(body -> {
                            // 业务逻辑处理
                        });
                    })
                    // 处理发送失败
                    .onFailure(err -> {
                        // 错误日志或重试逻辑
                    });
        })
        // 处理请求创建失败
        .onFailure(err -> {
            // 错误日志或降级逻辑
        });

优化建议

  • 复用Payload对象:一次性完成Base64解码并生成Buffer,所有请求复用该对象,减少内存对象的频繁创建与回收。
  • 开启内存泄漏检测:启动JVM时添加参数-Dvertx.debug=true -Dvertx.leakCheck=true,帮助定位未释放的异步资源。
  • 调整GC策略:针对大对象场景,使用G1GC或ZGC,配置参数如-XX:+UseG1GC -XX:MaxGCPauseMillis=200,提升大对象的回收效率。
  • 监控请求状态:通过Vert.x内置的Metrics监控活跃请求数、等待队列长度,动态调整连接池参数,避免请求堆积。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:05:31