PHP 預設輸出緩衝,瀏覽器需等腳本結束才收到內容。長連接需:
set_time_limit(0) 移除執行時間限制。ob_flush() → flush() 強制推送至瀏覽器。sleep() 控制推送頻率。<?php
echo "每隔3秒輸出一次<br/>";
set_time_limit(0); // 關鍵:防止 30 秒超時
while (true) {
echo date('H:i:s') . "<br/>";
ob_flush(); // 刷新 PHP 內部緩衝
flush(); // 刷新 Web Server 緩衝發送給瀏覽器
sleep(3);
}
set_time_limit(0);
header('Connection: Keep-Alive');
header('Proxy-Connection: Keep-Alive');
for ($i = 0; $i < 60; $i++) {
echo "text$i<br>";
ob_flush();
flush();
sleep(1);
clearstatcache(); // 清除檔案狀態緩存(可選)
}
// ✅ 正確
ob_flush();
flush();
// ❌ 錯誤順序(Linux 下無輸出)
flush();
ob_flush();
Windows 上順序顛倒可能仍正常,但 Linux/Unix 環境下 必須先 ob_flush 再 flush。
若內容過少,Web Server 會繼續緩衝不發送。解法:在迴圈前輸出足夠空白字元。
// 確保緩衝區滿 4096 bytes
echo str_repeat(' ', 4096);
for ($i = 10; $i > 0; $i--) {
echo "$i<br/>";
ob_flush();
flush();
sleep(1);
}
ob_end_flush(); // 結束輸出緩衝
| 現象 | 可能原因 | 解決 |
|---|---|---|
| 瀏覽器一次性收到所有內容 | 未呼叫 ob_flush/flush 或順序錯誤 | 檢查順序、確保 output_buffering 門檻 |
| 連線中斷 (ERR_CONNECTION_RESET) | 腳本執行超時 | set_time_limit(0) 或 nginx proxy_read_timeout |
| 記憶體耗盡 | 無限迴圈未釋放資源 | 加入迴圈上限、定期 gc_collect_cycles() |
fastcgi_buffering 或設定 proxy_buffering off。mod_deflate 不攔截串流輸出。掌握 set_time_limit(0)、ob_flush() → flush()、4096 bytes 門檻 三要素,即可在傳統 PHP-FPM 架構下實現簡易串流輸出。但務必評估併發壓力,必要時遷移至常駐記憶體框架。