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

Helidon WebClient每请求新建连接致连接耗尽问题咨询

问题描述

使用Scala编写Helidon WebClient进行单线程压测,执行100万次POST请求时,约1.7万次后抛出java.net.BindException: Can't assign requested address错误。通过netstat查看发现大量处于TIME_WAIT状态的TCP连接,相关代码如下:

客户端初始化代码:

val client = WebClient
    .builder()
    .baseUri(s"http://localhost:8081")
    .build()

请求处理逻辑:

val r = client.post(uri).submit(data)
try
  val e = r.entity()
  e.as(arrayOfBytes)
finally r.close()

疑问:已关闭HttpClientResponse但连接仍无法复用,是否操作有误?能否配置WebClient复用连接,还是需要自行实现连接池?


解决方案

问题根源

  1. Helidon WebClient 连接池Bug:当前使用的版本存在连接复用失效问题,即便正确关闭响应对象,连接也无法被回收复用,导致每次请求都新建TCP连接。
  2. TIME_WAIT 端口耗尽:macOS的临时端口数量有限,大量新建连接在关闭后进入TIME_WAIT状态,无法快速释放,最终耗尽所有可用端口引发异常。

修复步骤

1. 显式配置连接池

通过WebClient Builder开启并配置连接池参数,强制实现连接复用:

import java.time.Duration

val client = WebClient
  .builder()
  .baseUri("http://localhost:8081")
  .connectionPool()
    .maxSize(5) // 单线程场景下,少量连接即可满足复用需求
    .idleTimeout(Duration.ofSeconds(30))
    .build()
  .build()

2. 确保响应实体被完整消费

若实体流未被完整读取,部分实现会标记连接为不可复用,需确保entity().as(arrayOfBytes)完整读取响应内容:

val response = client.post(uri).submit(data)
try {
  val responseBytes = response.entity().as(arrayOfBytes)
  // 处理响应数据
} finally {
  response.close()
}

3. 系统层面临时调整(可选)

临时修改macOS TCP参数,缩短TIME_WAIT状态的持续时间(重启后失效):

sudo sysctl -w net.inet.tcp.msl=1000
sudo sysctl -w net.inet.tcp.wait.timeout=1000

长期建议

优先升级Helidon至修复该连接池Bug的版本,从根源解决连接复用问题。

内容的提问来源于stack exchange,提问作者kostas.kougios

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:35:05