PHP 原生不支援多執行緒,所有程式碼預設同步阻塞執行。當需要發送郵件、呼叫外部 API、處理影片轉碼等耗時任務時,若同步等待回應,會嚴重拖慢使用者回應速度。非同步請求讓主流程「發送後即忘記」,背景任務獨立執行,大幅提升吞吐量與使用者體驗。
利用 curl_multi_* 系列函數並行發送多個 HTTP 請求,或設定極短逾時達成「發射後不理」效果。
<?php
// 發射後不理:設定 1 秒逾時,主程式不等待回應
$ch = curl_init('https://api.example.com/notify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query(['event' => 'order_created']),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 1, // 最小 1 秒
CURLOPT_NOSIGNAL => true, // 避免信號干擾
]);
curl_exec($ch); // 1 秒後繼續,無論回應與否
curl_close($ch);
// 後續主程式邏輯繼續執行...
echo '訂單建立成功,通知已發送';
?>
優點: 相容性好、支援完整 HTTP 協定、可攜帶複雜 Header/Body。
缺點: 最小逾時 1 秒仍有阻塞、大量併發易耗盡連線資源、無法獲取執行結果。
popen() 執行背景程序開啟一個指向命令的管道,啟動獨立 PHP 進程處理背景任務。
<?php
// 背景執行獨立腳本,主程式立即繼續
$cmd = '/usr/bin/php /var/www/tasks/send_email.php ' . escapeshellarg($userId) . ' > /dev/null 2>&1 &';
pclose(popen($cmd, 'r'));
// 主程式繼續...
echo '註冊成功,歡迎信已排程發送';
?>
優點: 真正非阻塞、可執行任意 CLI 指令、不受 HTTP 逾時限制。
缺點: 單向管道(無法讀取輸出)、高併發產生大量進程拖垮系統、需妥善管理進程生命週期、Windows 相容性較差。
fsockopen() 底層 Socket 非阻塞手動組裝 HTTP Request 透過 TCP 連線發送,設定非阻塞模式立即返回。
<?php
$host = 'api.example.com';
$path = '/webhook';
$data = json_encode(['event' => 'payment_success']);
$fp = fsockopen($host, 80, $errno, $errstr, 2);
if ($fp) {
stream_set_blocking($fp, 0); // 關鍵:非阻塞模式
$request = "POST $path HTTP/1.1\r\n";
$request .= "Host: $host\r\n";
$request .= "Content-Type: application/json\r\n";
$request .= "Content-Length: " . strlen($data) . "\r\n";
$request .= "Connection: Close\r\n\r\n";
$request .= $data;
fwrite($fp, $request);
fclose($fp); // 立即關閉,不讀取回應
} else {
error_log("Socket 連線失敗: $errstr ($errno)");
}
?>
優點: 極低延遲、無外部依賴、完全控制協定細節。
缺點: 需手動處理 HTTP 協定細節(Chunked、Redirect、SSL 等)、錯誤處理複雜、HTTPS 需額外啟用 ssl:// 封裝協定與憑證驗證。
上述三種方法屬於「應用層臨時方案」,生產環境高併發場景建議引入訊息佇列:
<?php
// Laravel Queue 範例
use App\Jobs\SendWelcomeEmail;
Route::post('/register', function () {
// ... 驗證與建立使用者 ...
SendWelcomeEmail::dispatch($user); // 丟入佇列,立即返回回應
return response()->json(['message' => '註冊成功']);
});
?>
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 簡單通知、Webhook、低併發 | cURL 短逾時 | 零依賴、快速上線 |
| 定時任務、影片轉碼、大量運算 | popen() + CLI 腳本 | 脫離 Web 進程、無執行時間限制 |
| 極高併發、微服務內部通訊 | fsockopen / Swoole / RoadRunner | 繞過 HTTP 封裝開銷、支援協程 |
| 生產系統核心業務流程 | 訊息佇列 (Redis/RabbitMQ/Kafka) | 可靠性、可觀測性、重試機制、擴展性 |
PHP 雖無原生多執行緒,但透過 cURL、popen、fsockopen 等方式可模擬非同步行為。隨著業務增長,務必盡早遷移至訊息佇列架構,將「發送任務」與「執行任務」徹底解耦,構建高可用、可擴展的系統。