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

WebSphere Liberty部署应用后HTTPClient5.3.1出现CLOSE_WAIT问题咨询

问题:WebSphere Liberty共享JVM下HTTPClient 5连接池部署后出现CLOSE_WAIT连接

背景与实现

我们使用WebSphere Liberty Profile托管多个应用,所有应用运行在同一JVM下。部分应用采用HTTPClient 5.3.1调用API,连接池实现代码如下:

ConnectionConfig connConfig = ConnectionConfig.custom()
                .setConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
                .setValidateAfterInactivity(validateAfterInactivity, TimeUnit.MILLISECONDS)
                .setSocketTimeout(socketTimeout, TimeUnit.MILLISECONDS)
                .setTimeToLive(TimeValue.ofSeconds(timeToLive))                 
                .build();

        //Building the custom Request config
        RequestConfig requestConfig = RequestConfig.custom()                        
                .setConnectionRequestTimeout(connectionRequestTimeout, TimeUnit.MILLISECONDS)
                .setResponseTimeout(connectionRequestTimeout, TimeUnit.MILLISECONDS)                
                .build();

        connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                  .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create()
                          .setSslContext(SSLContexts.createSystemDefault())                               
                          .build())
                  .setDefaultSocketConfig(SocketConfig.custom()
                         .setSoTimeout(socketTimeout, TimeUnit.MILLISECONDS)                               
                          .build())                       
                  .setDefaultConnectionConfig(connConfig)               
                  .setMaxConnTotal(maxTotal)
                  .setMaxConnPerRoute(defaultMaxPerRoute)   
                  .build();                         

        //Building the http Client
        httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setConnectionManagerShared(true)
                .setDefaultRequestConfig(requestConfig)     
                .evictExpiredConnections()                       
                .setKeepAliveStrategy(keepAliveStrategy) 
                .disableConnectionState()                        
                .evictIdleConnections(TimeValue.ofSeconds(evictIdleTime))                            
                .build();       

问题现象

连接池日常工作正常,可正常关闭socket,但在部署曾使用该连接池的应用时,系统会新建连接,而连接池中的部分socket会处于CLOSE_WAIT状态:

TCP    <localhostip>:49260    <remoteserverip>:443      CLOSE_WAIT      17068
TCP    <localhostip>:49362    <remoteserverip>:443      CLOSE_WAIT      17068
TCP    <localhostip>:49363    <remoteserverip>:443      CLOSE_WAIT      17068
TCP    <localhostip>:49364    <remoteserverip>:443      CLOSE_WAIT      17068
TCP    <localhostip>:49365    <remoteserverip>:443      CLOSE_WAIT      17068
TCP    <localhostip>:49366    <remoteserverip>:443      CLOSE_WAIT      17068

该问题仅在部署应用时出现,且因JVM为其他应用共享,无法重启进程。现咨询:

  1. 此是否为Apache HTTPClient5的Bug,有无修复方案?
  2. 在Windows服务器上能否从socket层面清除CLOSE_WAIT状态?
  3. 有无其他修复方案?无法使用JVM关闭事件。

解答

1. 是否为HTTPClient 5的Bug及修复方案

这大概率不是HTTPClient 5的原生Bug,而是共享连接池在应用热部署时的资源未正确释放导致的。

  • 你设置了setConnectionManagerShared(true),意味着连接池被多个应用共享,但WebSphere Liberty热部署时,旧应用的类加载器会被卸载,若旧应用持有连接池的引用未正确清理,连接池中的连接会因为引用残留,无法触发正常的关闭逻辑,导致远端主动关闭连接后,本地socket停留在CLOSE_WAIT状态。
  • 修复方向:
    • 避免在热部署场景下使用共享连接池,改为每个应用独立维护自己的连接池实例。
    • 若必须共享,可监听WebSphere Liberty的应用生命周期事件(比如javax.servlet.ServletContextListener的contextDestroyed方法),在应用卸载时主动调用connectionManager.closeExpiredConnections()和connectionManager.closeIdleConnections(TimeValue.ZERO),强制回收所有空闲连接。
    • 升级HTTPClient 5到最新稳定版本(如5.4.x),检查官方是否有相关资源泄漏的修复补丁。

2. Windows服务器上能否从socket层面清除CLOSE_WAIT状态

从操作系统层面,无法直接强制清除CLOSE_WAIT状态的socket。CLOSE_WAIT状态表示远端已经关闭连接,本地应用尚未调用close()释放socket资源。只有当持有该socket的进程主动关闭它,或者进程终止,socket才会被系统回收。

  • Windows上没有类似Linuxss/tcpkill的工具可以直接强制关闭属于某个进程的特定socket,除非终止对应的进程,但你无法重启JVM,所以这个路径不可行。

3. 其他修复方案

除上述方案外,还有以下几种思路:

  • 强化连接池自动回收策略:
    • 缩短validateAfterInactivity的时间,让连接池更频繁地检查连接有效性,发现已失效的CLOSE_WAIT连接时主动关闭。
    • 进一步降低evictIdleTime,设置更短的空闲连接驱逐周期,配合evictIdleConnections定时清理空闲连接。
  • 添加连接有效性校验:在每次从连接池获取连接时,使用HTTPClient的setConnectionValidator自定义校验逻辑,若发现连接处于失效状态(如CLOSE_WAIT),直接丢弃并重新创建连接。
  • 启用应用类加载器隔离:调整WebSphere Liberty的配置,启用应用类加载器的严格隔离,确保旧应用的资源(包括连接池引用)在热部署时被完全清理,避免残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:41:05