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

PHP cURL HTTPS 請求記憶體洩漏問題根因與解決方案

     編輯:PHP 綜合知識

問題現象

長時間運行的 PHP CLI 腳本(如爬蟲、資料同步)使用 cURL 透過 HTTP Proxy 存取 HTTPS 網站時,記憶體使用量持續增長,top 觀察到 RSS 不斷上升,但 memory_get_usage() 回報正常。重啟腳本後記憶體釋放,確認為 cURL 底層洩漏。

根本原因

cURL 在處理 HTTPS over HTTP Proxy 時,若未啟用 CURLOPT_HTTPPROXYTUNNEL,預設使用 HTTP CONNECT 建立隧道,但某些版本的 libcurl/OpenSSL 在重複建立 TLS 連線時,未正確釋放 SSL_CTX 或連線緩衝區,導致底層 C 堆疊記憶體洩漏。PHP 的記憶體管理器無法追蹤此類洩漏。

解決方案:關鍵 cURL 選項組合

$ch = curl_init();

$options = [
    CURLOPT_URL            => 'https://www.google.com/search?q=test',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_TIMEOUT        => 30,

    // === 關鍵三項 ===
    CURLOPT_HTTPPROXYTUNNEL => true,  // 1. 強制使用 HTTP CONNECT 隧道
    CURLOPT_SSL_VERIFYPEER  => false, // 2. 跳過憑證驗證(測試環境;生產請配合 CA Bundle)
    CURLOPT_SSL_VERIFYHOST  => false, // 3. 跳過主機名驗證(同上)

    // Proxy 設定(視環境調整)
    CURLOPT_PROXY          => 'https://127.0.0.1:8118', // Privoxy 預設
    CURLOPT_PROXYTYPE      => CURLPROXY_HTTP,
];

curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);

選項詳細說明

選項值作用
CURLOPT_HTTPPROXYTUNNELtrue強制 cURL 向 Proxy 發送 CONNECT 指令建立 TCP 隧道,Proxy 僅轉發加密資料流,不解析 HTTP 標頭。避免 Proxy 層級的緩衝/重寫導致的洩漏。
CURLOPT_SSL_VERIFYPEERfalse跳過伺服器憑證鏈驗證。生產環境請設為 true 並指定 CURLOPT_CAINFO。
CURLOPT_SSL_VERIFYHOSTfalse (或 0)跳過憑證 CN/SAN 與主機名比對。生產環境請設為 2。

生產環境安全配置建議

// 生產環境:嚴格驗證 + 指定 CA Bundle
curl_setopt_array($ch, [
    CURLOPT_HTTPPROXYTUNNEL => true,
    CURLOPT_SSL_VERIFYPEER  => true,
    CURLOPT_SSL_VERIFYHOST  => 2,
    CURLOPT_CAINFO          => '/etc/ssl/certs/ca-certificates.crt', // Debian/Ubuntu
    // CURLOPT_CAPATH       => '/etc/ssl/certs', // 或指定目錄
    CURLOPT_PROXY           => 'https://proxy.example.com:3128',
    CURLOPT_PROXYUSERPWD    => 'user:pass', // 若 Proxy 需認證
]);

驗證洩漏是否解決

# 1. 撰寫測試腳本 loop_curl.php,迴圈 1000 次請求
# 2. 監控記憶體
watch -n 1 'ps -o pid,rss,cmd -p $(pgrep -f loop_curl.php)'

# 3. 對比修正前後 RSS 增長趨勢
# 修正前:RSS 持續線性增長
# 修正後:RSS 穩定在固定區間(±幾 MB)

補充:多執行緒/多行程環境

  • 使用 curl_multi_* 非阻塞介面時,同樣需在每個 handle 設定上述三項選項。
  • 共用 CURLSHOPT_SSL_SESSION_CACHE 可重用 SSL Session,減少握手開銷與洩漏風險:
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
curl_setopt($ch, CURLOPT_SHARE, $sh);

版本相容性提醒

  • PHP 5.5+ / libcurl 7.30+ 完整支援上述選項。
  • 舊版 libcurl 可能不支援 CURLOPT_HTTPPROXYTUNNEL,建議升級系統套件:yum update curl libcurl 或 apt upgrade libcurl4。

正確配置 cURL Proxy 與 SSL 選項,能徹底解決長期運行 HTTPS 請求的記憶體洩漏問題,確保爬蟲、同步任務穩定執行。

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