首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP cURL 訪問 HTTPS 內存洩漏根因分析與三參數修復方案

     編輯:PHP 相關知識

長時間運行的 cURL 多線程採集 HTTPS 頁面 (經 Privoxy 代理) 出現嚴重內存洩漏,memory_get_usage() 無感知,僅 top 觀察到 RSS 持續增長。經排查,需同時設置三個 SSL/代理相關選項徹底解決。

現象

  • cURL 循環請求 https://www.google.com/search?q=xxx 經 HTTP 代理。
  • 單/多線程均洩漏,memory_get_usage() 正常,進程 RSS 線性增長。
  • 改請 HTTP 頁面不洩漏,確認為 HTTPS 相關。

修復配置

curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);  // 關鍵:建立 TCP 隧道
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // 跳過證書驗證
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 不檢查證書 CN

原理深度解析

CURLOPT_HTTPPROXYTUNNEL = true

無隧道模式 (默認):

  1. 客戶端發送完整 HTTP 請求給代理
  2. 代理解析 Header,提取目標 Host,轉發請求
  3. 代理接收響應,轉發給客戶端
  4. 問題:代理需緩存完整請求/響應,HTTPS 握手數據經代理解析可能導致 OpenSSL 內部緩衝區未正確釋放

隧道模式:

  1. 客戶端發送 CONNECT host:443 給代理
  2. 代理建立 TCP 連接到目標,返回 200 Connection established
  3. 後續數據雙向透傳,**代理不再解析 HTTP/SSL 層**
  4. OpenSSL 直接與目標服務器交互,避免中間層緩衝區殘留

SSL 驗證選項

  • CURLOPT_SSL_VERIFYPEER=false:不驗證證書鏈信任鏈,避免 CA 束加載/驗證邏輯的內存殘留。
  • CURLOPT_SSL_VERIFYHOST=0 (或 false):不檢查證書 Common Name,進一步減少 SSL 上下文分配。

驗證方法

// 壓測腳本
for ($i=0; $i<10000; $i++) {
    curl_exec($ch);
    if ($i % 100 === 0) {
        echo "RSS: " . (memory_get_usage(true)/1024/1024) . " MB\n";
        // 同時 top -p PID 觀察 RES
    }
}

修復前:RSS 每 1000 請求增長 ~50MB
修復後:RSS 穩定在基線 ±2MB

生產環境建議

  1. 保留證書驗證:生產應設置 CURLOPT_CAINFO 指定 CA 憑證包,而非關閉驗證。
  2. 複用句柄:curl_reset($ch) 重置選項,避免重複 curl_init/close 開銷。
  3. 監控指標:Prometheus 采集 process_resident_memory_bytes 設置告警閾值。

內存洩漏多發於 C 擴展與外部庫交互邊界,CURLOPT_HTTPPROXYTUNNEL 是 HTTPS 代理場景的「銀彈」,務必默認開啟。

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