簡體   English   中英

運行並發PHP腳本

[英]Running concurrent PHP scripts

我的VPS服務器出現以下問題。

我有一個長期運行的PHP腳本,它將大文件發送到瀏覽器。 它執行以下操作:

<?php
header("Content-type: application/octet-stream");
readfile("really-big-file.zip");
exit();
?>

這基本上是從服務器的文件系統讀取文件並將其發送到瀏覽器。 我不能只使用直接鏈接(並讓Apache提供文件),因為應用程序中需要應用業務邏輯。

問題在於,在運行此類下載時,該站點不會響應其他請求。

您遇到的問題與您正在使用會話有關。 當腳本具有正在運行的會話時,它將鎖定會話文件,以防止可能導致會話數據損壞的並發寫入。 這意味着來自同一客戶端的多個請求(使用相同的會話ID)將不會同時執行,它們將排隊,並且一次只能執行一個。

多個用戶將不會遇到此問題,因為他們將使用不同的會話ID。 這並不意味着您沒有問題,因為您可能會想在下載文件時訪問該站點,或者設置一次下載多個文件。

解決方案實際上非常簡單:在開始輸出文件之前,請調用session_write_close() 這將關閉會話文件,釋放鎖並允許進一步的並發請求執行。

服務器設置可能不是您應該檢查的唯一位置。

嘗試照常從瀏覽器發出請求,然后再從其他客戶端發出另一個請求。

從同一台計算機上的wget或另一台計算機上的另一個瀏覽器。

服務器不以什么方式響應其他請求? 是“正在等待example.com ...”還是給出任何錯誤?

我做類似的事情,但我將文件分塊處理,這使文件系統在客戶端接受並下載塊時有所中斷,這比一次提供全部內容要好,這對文件系統和整個服務器。

編輯:雖然不是這個問題的答案,但問問者詢問了如何讀取分塊的文件。 這是我使用的功能。 提供文件的完整路徑。

function readfile_chunked($file_path, $retbytes = true)
{
$buffer = '';
$cnt = 0;
$chunksize = 1 * (1024 * 1024); // 1 = 1MB chunk size
$handle = fopen($file_path, 'rb');
if ($handle === false) {
    return false;
}
while (!feof($handle)) {
    $buffer = fread($handle, $chunksize);
    echo $buffer;
    ob_flush();
    flush();
    if ($retbytes) {
        $cnt += strlen($buffer);
    }
}
    $status = fclose($handle);
    if ($retbytes && $status) {
        return $cnt; // return num. bytes delivered like readfile() does.
}
    return $status;
}

同樣的事情發生在我身上,我沒有使用會話。 session.auto_start設置為0我的示例腳本僅運行“ sleep(5)”,並且在開頭添加“ session_write_close()”不能解決問題。

檢查您的httpd.conf文件。 也許您具有“ KeepAlive On”功能,這就是為什么您的第二個請求掛起直到第一個請求完成。 通常,您的PHP腳本不應允許訪問者等待很長時間。 如果您需要下載較大的內容,請在用戶無法直接控制的單獨內部請求中進行下載。 在完成之前,向最終用戶返回一些“正在執行”狀態,完成后將處理實際結果。

我嘗試了不同的方法(使用PEARs HTTP_Download讀取和發送小塊文件(請參見PHP文檔中有關readfile注釋),但是當文件變大時,我總是會遇到性能問題。

有一個Apache mod X-Sendfile ,您可以在其中執行業務邏輯,然后將下載委派給Apache。 該下載將不會公開提供。 我認為,這是解決該問題的最優雅的方法。

更多信息:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM