在PHP 開發中,頻繁調用RESTful 接口是非常常見的場景,尤其是在微服務架構中,不同服務之間的通信往往依賴HTTP 請求。而cURL是PHP 中處理HTTP 請求最常用的擴展。雖然單次請求的性能開銷通常可以接受,但在高並發場景下,如果每個請求都重複初始化連接資源,將會造成不小的性能瓶頸。
這時候, curl_share_init()函數就派上用場了。它提供了一種資源共享機制,允許多個cURL 句柄共享DNS 緩存、SSL 會話等信息,從而減少連接建立的時間,進而提升整體接口請求的效率。
curl_share_init()是cURL 提供的一個資源共享初始化函數,它會返回一個cURL Share 句柄。通過這個句柄,你可以配置多個cURL 請求共享特定的資源,例如:
DNS 緩存( CURLSHOPT_SHARE與CURL_LOCK_DATA_DNS )
Cookie ( CURLSHOPT_SHARE與CURL_LOCK_DATA_COOKIE )
SSL 會話( CURLSHOPT_SHARE與CURL_LOCK_DATA_SSL_SESSION )
這些共享數據可以顯著減少每次請求的重複計算與握手操作。
假設我們需要並發請求多個服務接口,例如:
https://api.m66.net/service1
https://api.m66.net/service2
https://api.m66.net/service3
以下是使用curl_share_init()實現資源共享的完整PHP 示例:
<?php
// 初始化共享句柄
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
// 要請求的 URL 數組
$urls = [
'https://api.m66.net/service1',
'https://api.m66.net/service2',
'https://api.m66.net/service3',
];
// 初始化 curl_multi 句柄
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SHARE, $sh); // 設置共享資源
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
// 執行並發請求
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
// 獲取結果
foreach ($handles as $ch) {
$response = curl_multi_getcontent($ch);
echo "Response: " . $response . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
// 清理資源
curl_share_close($sh);
curl_multi_close($mh);
?>
使用curl_share_init()的好處主要體現在以下幾個方面:
DNS 緩存共享:避免每個請求都重複進行域名解析,尤其對於多個請求都訪問同一域名時收益明顯。
SSL 會話重用:減少SSL 握手開銷,尤其在HTTPS 接口調用頻繁的場景下節省CPU 資源。
連接效率提升:當與HTTP Keep-Alive 配合使用時,可以極大提升接口請求效率。
在高並發環境或需要頻繁調用多個接口的應用場景中,合理利用curl_share_init()可以顯著提升系統整體性能和響應速度。
並非所有資源都適合共享,尤其是Cookie,可能會引發安全或狀態污染問題。
必須在所有使用完共享資源的cURL 句柄關閉後,再關閉共享資源。
不是所有PHP 安裝都開啟了cURL 的共享支持,可以通過curl_version()檢查支持情況。