利用 cURL 多執行緒一次發送多個 HTTP 請求,適用於需並行呼叫外部 API 的場景。缺點:走網路通訊,效率與可靠性受限於網路環境。
function sendMulitRequest($send_data) {
$handle = curl_multi_init();
foreach ($send_data as $k => $v) {
$curl[$k] = curl_init();
curl_setopt($curl[$k], CURLOPT_URL, $v['url']);
curl_setopt($curl[$k], CURLOPT_POST, true);
curl_setopt($curl[$k], CURLOPT_RETURNTRANSFER, 1);
curl_multi_add_handle($handle, $curl[$k]);
}
$active = null;
do { $mrc = curl_multi_exec($handle, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($handle) != -1) {
do { $mrc = curl_multi_exec($handle, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
// 收集結果...
return $text;
}
使用 stream_socket_client 配合 STREAM_CLIENT_ASYNC_CONNECT 與 stream_select 實現非阻塞並發 Socket 通訊,適合高效能長連線場景。
$s = stream_socket_client($host . ":80", $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);
if ($s) { $sockets[$id++] = $s; fwrite($s, $http_message); }
// stream_select 監聽可讀寫...
利用 pcntl_fork 建立子進程,父進程管理進程池,子進程執行任務。需注意訊號處理(SIGCHLD)避免殭屍進程。
function daemon($func_name, $args, $number) {
while (true) {
$pid = pcntl_fork();
if ($pid == -1) exit();
elseif ($pid) { // 父進程
static $num = 0;
if (++$num >= $number) { pcntl_wait($status); $num--; }
} else { // 子進程
while (true) { call_user_func_array($func_name, $args); sleep(2); }
exit();
}
}
}
curl_multistream_socketpcntl_fork