2024 PHP Conference Japan

fastcgi_finish_request

(PHP 5 >= 5.3.3, PHP 7, PHP 8)

fastcgi_finish_request將所有回應資料送出至客戶端

說明

fastcgi_finish_request(): 布林值

此函式會將所有回應資料送出至客戶端並結束請求。這允許在不保持與客戶端的連線開啟的情況下執行耗時的工作。

參數

此函式沒有參數。

回傳值

成功時回傳 true,失敗時回傳 false

新增註釋

使用者貢獻的註釋 3 則註釋

tuxrampage
8 年前
使用此函式時,有一些陷阱需要注意。

在呼叫 `fastcgi_finish_request()` 之後,腳本仍會佔用一個 FPM 程序。因此,過度使用它來執行長時間的任務可能會佔用所有 FPM 執行緒,達到 `pm.max_children` 的上限。這將導致 Web 伺服器出現閘道錯誤。

另一個重點是 Session 的處理。Session 在活動狀態時會被鎖定(請參閱 `session_write_close()` 的文件)。這表示後續的請求將會被阻塞,直到 Session 關閉為止。

因此,您應該儘快呼叫 `session_write_close()`(甚至在 `fastcgi_finish_request()` 之前),以便允許後續請求並提供良好的使用者體驗。

這也適用於所有其他鎖定技術,例如 `flock` 或資料庫鎖。只要鎖定處於活動狀態,後續的請求就可能會被阻塞。
rundiz dot com
3 年前
以下是幾個使用範例。

第一個是基本範例。

<?php
$file
= __DIR__ . '/text.txt';

if (
is_file($file) && is_writable($file)) {
@
unlink($file);
echo
'<small style="color: #ccc;">' . $file . ' 已刪除。</small><br>' . PHP_EOL;
}

echo
'<p>呼叫 <code>fastcgi_finish_request()</code>。</p>' . PHP_EOL;

echo
'<p>如果成功,檔案 ' . $file . ' 將會被建立。</p>' . PHP_EOL;

if (
function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
} else {
echo
'<p style="color: red;">此伺服器不支援 <code>fastcgi_finish_request()</code> 函式。</p>' . PHP_EOL;
echo
'現在結束。<br>' . PHP_EOL;
exit();
}

echo
'這行不會被輸出。<br>' . PHP_EOL;

file_put_contents($file, date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);
?>

如果成功,檔案 text.txt 將會被建立。

==========================

第二個是關於執行逾時的範例。

<?php
設定執行時間限制
(5);

$file = __DIR__ . '/text.txt';

if (
is_file($file) && is_writable($file)) {
@
unlink($file);
echo
'<small style="color: #ccc;">' . $file . ' 已刪除。</small><br>' . PHP_EOL;
}

echo
'<p>測試逾時和 <code>fastcgi_finish_request()</code> 函式。</p>' . PHP_EOL;

echo
'<p>設定逾時為 ' . ini_get('max_execution_time') . ' 秒。</p>' . PHP_EOL;

echo
'<p>呼叫 <code>fastcgi_finish_request()</code>。</p>' . PHP_EOL;

echo
'<p>如果成功,檔案 ' . $file . ' 將會被建立,但錯誤訊息會顯示在日誌中。</p>' . PHP_EOL;

if (
function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
} else {
echo
'<p style="color: red;">此伺服器不支援 <code>fastcgi_finish_request()</code> 函式。</p>' . PHP_EOL;
echo
'現在退出。<br>' . PHP_EOL;
exit();
}

$i = 1;
while(
true){
if (
$i <= 10) {
file_put_contents($file, date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);
$i++;
}
//直到永遠…
}
?>

我發現只要程式碼沒有超過 php.ini 或 set_time_limit() 函式設定的逾時時間,它就會持續運作。
john at jrcii dot com
10 個月前
mike@php.net 認為這 https://bugs.php.net/bug.php?id=68772「不是 bug」,但請注意

如果您在呼叫 fastcgi_finish_request() 之後寫入緩衝區(使用 print 陳述式等),您的腳本將會在沒有任何錯誤訊息或例外的情況下退出。在 fastcgi_finish_request() 之後呼叫 ignore_user_abort(true) 可以減輕這個問題。
To Top