在使用PHP 進行網絡請求時,我們常用到cURL 庫。 cURL 是一個強大的工具,它不僅支持簡單的HTTP 請求,還支持如cookie、DNS、SSL 等高級特性。
其中, curl_share_init是一個比較少為人知的cURL 特性,它允許多個cURL 句柄共享數據,比如DNS 緩存、cookie、SSL session 等。通過共享DNS 緩存,我們可以減少重複的域名解析,提高性能。
但在實際使用中,很多人會疑問:
共享的DNS 緩存到底有沒有生效?要如何監控?
本文就帶你一步步分析,並給出完整的PHP 示例。
curl_share_init()函數用於初始化一個共享句柄,配合curl_setopt的CURLOPT_SHARE選項,可以讓多個cURL 請求共享某些數據。常見共享的內容包括:
DNS 緩存( CURL_LOCK_DATA_DNS )
Cookie( CURL_LOCK_DATA_COOKIE )
SSL 會話( CURL_LOCK_DATA_SSL_SESSION )
例如:
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
這樣多個cURL 句柄綁定同一個$sh ,就能共享DNS 緩存。
雖然cURL 沒有直接提供“監控DNS 緩存命中”的接口,但我們可以間接觀察:
首次請求耗時:首次請求通常包含DNS 解析時間。
後續請求耗時:如果啟用了共享DNS,後續相同域名的請求應明顯減少解析時間。
換句話說,我們可以用CURLINFO_NAMELOOKUP_TIME和CURLINFO_TOTAL_TIME兩個cURL 選項,分別監控:
域名解析時間
總耗時
通過比較首個請求與後續請求的NAMELOOKUP_TIME ,就能判斷DNS 緩存是否生效。
以下是一個使用curl_share_init的完整PHP 代碼,向https://m66.net/test發送兩次請求,並打印DNS 解析時間:
<?php
$sh = curl_share_init();
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
$url = 'https://m66.net/test';
// 第一次請求
$ch1 = curl_init($url);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_SHARE, $sh);
curl_exec($ch1);
$dns_time1 = curl_getinfo($ch1, CURLINFO_NAMELOOKUP_TIME);
$total_time1 = curl_getinfo($ch1, CURLINFO_TOTAL_TIME);
curl_close($ch1);
echo "第一次請求:\n";
echo "DNS 解析時間: {$dns_time1} 秒\n";
echo "總耗時: {$total_time1} 秒\n";
// 等待1秒,模擬新的請求
sleep(1);
// 第二次請求
$ch2 = curl_init($url);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_SHARE, $sh);
curl_exec($ch2);
$dns_time2 = curl_getinfo($ch2, CURLINFO_NAMELOOKUP_TIME);
$total_time2 = curl_getinfo($ch2, CURLINFO_TOTAL_TIME);
curl_close($ch2);
echo "\n第二次請求:\n";
echo "DNS 解析時間: {$dns_time2} 秒\n";
echo "總耗時: {$total_time2} 秒\n";
// 清理
curl_share_close($sh);
?>
?啟用共享:用curl_share_init和CURLSHOPT_SHARE配置共享DNS 數據。
?獲取時間:通過curl_getinfo拿到CURLINFO_NAMELOOKUP_TIME 。
?對比效果:第一次請求通常會有明顯的DNS 耗時(比如幾十毫秒);第二次如果緩存生效, NAMELOOKUP_TIME會接近0。
同一域名:只有相同的主機名(例如m66.net )才能命中緩存。
PHP cURL 版本:部分老版本PHP 可能不完全支持curl_share 。建議用phpinfo()檢查cURL 版本。
線程安全:如果在多線程或多進程環境下使用curl_share ,需要確保加鎖安全。