首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

項目上線前夕遭遇 CLOSE_WAIT 堆積?HttpClient 連接洩漏排查與修復實戰

     編輯:Java 綜合教學

現象描述

內測階段發現服務器連接數異常增長,netstat -an | grep CLOSE_WAIT 顯示大量 CLOSE_WAIT 狀態連接未釋放,隨時間增長最終導致文件描述符耗盡、服務不可用。

根因分析

CLOSE_WAIT 表示**被動關閉方**(服務端)已收到 FIN 並發送 ACK,但**應用層未調用 close() 釋放套接字**。Java 中常見於 HTTP 客戶端調用外部 API 後,未正確釋放連接資源。

定位代碼

排查發現調用短信供應商 HTTP 接口的工具類使用了 Apache HttpClient 3.x,但缺釋放連接邏輯:

// 問題代碼
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
// ... 設置參數、執行請求
client.executeMethod(method);
// 缺少釋放連接!

修復方案

在 finally 塊中確保釋放連接並關閉閒置連接管理器:

HttpClient client = new HttpClient();
PostMethod method = null;
try {
    method = new PostMethod(url);
    // 設置參數...
    client.executeMethod(method);
    // 處理響應...
} catch (Exception e) {
    log.error("HTTP 調用失敗", e);
    throw e;
} finally {
    if (method != null) {
        method.releaseConnection(); // 關鍵:歸還連接到管理器
    }
    // 關鍵:強制關閉閒置連接,防洩漏
    client.getHttpConnectionManager().closeIdleConnections(0);
}

最佳實踐升級建議

  1. 遷移至 HttpClient 4.5+ / HttpComponents Client 5:API 更清晰,支持 Try-with-resources 自動關閉。
  2. 使用連接池:PoolingHttpClientConnectionManager 統一管理連接生命周期,配合 CloseableHttpClient。
  3. 設置超時:連接超時、請求超時、Socket 超時三者必須全部配置,防止掛死。
  4. 監控指標:暴露連接池可用/閒置/租用數到 Prometheus,設置告警閾值。

HttpClient 4.x 正確姿勢示例

try (CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(poolingConnManager)
        .setDefaultRequestConfig(RequestConfig.custom()
                .setConnectTimeout(3000)
                .setSocketTimeout(5000)
                .setConnectionRequestTimeout(1000)
                .build())
        .build()) {

    HttpPost post = new HttpPost(url);
    post.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));

    try (CloseableHttpResponse response = httpClient.execute(post)) {
        // 處理 response.getEntity()...
        EntityUtils.consumeQuietly(response.getEntity()); // 確保流讀完歸還連接
    }
} // 自動關閉 client,歸還連接

修復上線後,CLOSE_WAIT 數量歸零,連接池穩定複用,上線風險徹底消除。記住:**每一次 HTTP 調用,都要對連接的歸還負責。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved