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

PHP 非同步執行長時間任務:fsockopen 實作與連線狀態控制

     編輯:PHP 綜合知識

為什麼需要非同步觸發?

Web 請求中若直接執行耗時腳本(如發送大量郵件、影片轉碼),使用者需等待回應,體驗極差。利用 fsockopen() 發起 HTTP 請求後不等待回應即關閉連線,即可達到「觸發即返回」的非同步效果。

核心函數:triggerRequest()

function triggerRequest($url, $post_data = [], $cookie = []) {
    $url_parts = parse_url($url);
    $host = $url_parts['host'];
    $port = $url_parts['port'] ?? 80;
    $path = $url_parts['path'] . ($url_parts['query'] ? '?' . $url_parts['query'] : '');

    $fp = fsockopen($host, $port, $errno, $errstr, 30);
    if (!$fp) return false;

    $method = empty($post_data) ? 'GET' : 'POST';
    $header = "$method $path HTTP/1.1\r\n";
    $header .= "Host: $host\r\n";
    $header .= "Connection: Close\r\n";

    if (!empty($cookie)) {
        $cookie_str = 'Cookie: ' . base64_encode(http_build_query($cookie, '', '; ')) . "\r\n";
        $header .= $cookie_str;
    }

    if (!empty($post_data)) {
        $body = http_build_query($post_data);
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($body) . "\r\n\r\n";
        $header .= $body;
    } else {
        $header .= "\r\n";
    }

    fwrite($fp, $header);
    fclose($fp); // 立即關閉,不讀取回應
    return true;
}

被觸發腳本必須設定的兩個關鍵項

<?php
// 1. 忽略用戶端斷線,讓腳本繼續跑完
ignore_user_abort(true);

// 2. 移除執行時間限制(預設 30 秒)
set_time_limit(0);

// 你的長時間任務邏輯...
// 例如:發送郵件、生成報表、視頻轉碼等

PHP 連線狀態常數

常數值說明
NORMAL0正常執行中
ABORTED1用戶端中斷連線(如點擊停止、關閉瀏覽器)
TIMEOUT2執行時間超過 max_execution_time

可用 connection_status() 取得當前狀態(位元組合,如 3 = ABORTED + TIMEOUT)。

進階:註冊關閉函數處理異常結束

register_shutdown_function(function() {
    $status = connection_status();
    if ($status & CONNECTION_ABORTED) {
        // 用戶端斷線,記錄日誌或清理資源
    }
    if ($status & CONNECTION_TIMEOUT) {
        // 執行超時
    }
});

替代方案比較

  • fsockopen:無額外依賴,適合簡單觸發。
  • cURL (CURLOPT_TIMEOUT_MS = 1):更穩健,支援 HTTPS、完整 Header 控制。
  • 消息佇列:Redis、RabbitMQ、Beanstalkd 等,適合高併發、需重試、監控的生產系統。
  • Swoole / Workerman:常駐進程框架,原生支援 TaskWorker 非同步任務。

總結

使用 fsockopen() 搭配 ignore_user_abort(true) 和 set_time_limit(0) 是 PHP 傳統環境下實現「即觸即走」非同步任務的最輕量方案。對於關鍵業務,建議升級至佇列系統保證可靠性。

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