瀏覽器和伺服器之間是通過http進行通訊的,瀏覽器傳送請求給伺服器,伺服器處理完請求後,傳送響應結果給瀏覽器,瀏覽器展示給使用者。如果伺服器處理請求時間比較長,那麼瀏覽器就需要等待伺服器的處理結果。
但是,有時候,瀏覽器不需要等待伺服器的處理結果,只要傳送的請求已經被伺服器接收到。所以,這種情況下,瀏覽器希望伺服器接收到請求立即返回乙個響應,比如字串'success'。這樣瀏覽器可以繼續執行後續**。
在php中,很容易做到。如果伺服器使用的是nginx+fpm,可以使用下面的**:
echo
'success';
fastcgi_finish_request();
// 執行耗時**.....
如果伺服器使用的是apache,可以使用下面的**:
ob_end_flush();
ob_start();
echo 'success';
header("content-type: text/html;charset=utf-8");
header("connection: close");
header('content-length: '. ob_get_length());
ob_flush();
flush();
// 執行耗時**.....
乙個靜態頁面:index.html,**如下:
測試php提前輸出響應title>
head>
script>
function
getcurtime(d)
function
getother(url)
});}console.log(getcurtime(new
date()));
$.ajax(
});script>
body>
html>
瀏覽器首先通過ajax請求a.php,該php檔案執行是比較耗時的,要等到a.php的響應後繼續請求b.php檔案。如果a.php不提前輸出響應,ajax必須等待響應後才能去請求b.php。
上面**,會在每次請求傳送開始和返回時列印出時間。
兩個php檔案:1.php 、 2.php
a.php檔案內容:
<?php
echo
'success';
sleep(5);
?>
上面**使用sleep函式模擬耗時任務,耗時5秒。
b.php檔案內容:
<?php
echo
'this is b.php';
?>
瀏覽器執行index.html,檢視console日誌如下:
console日誌
發現第二次請求時間比第一次請求時間遲5秒,正好是a.php檔案的執行時間,說明瀏覽器需要等待a.php檔案執行完才能去請求b.php檔案。
下面修改a.php檔案內容,提前輸出響應,**如下:
<?php
if(!function_exists('fastcgi_finish_request'))
echo
'success';
if(!function_exists('fastcgi_finish_request')) else
sleep(5);
?>
瀏覽器執行index.html,檢視console日誌如下:
console日誌
兩次請求的時間都一樣,表示a.php已經提前輸出響應了。
開發web應用程式不可避免的要用到session,修改一下a.php檔案內容如下:
<?php
session_start();
$_session['uname'] = 'jianshu';
if(!function
_exists('fastcgi_finish_request'))
echo 'success';
if(!function
_exists('fastcgi_finish_request')) else
sleep(5);
?>
修改b.php檔案內容如下:
<?php
session_start();
echo $_session['uname'];
echo
'this is b.php';
?>
瀏覽器執行index.html,檢視console日誌如下:
console日誌
發現第一次和第二次請求時間一樣,說明第一次請求已經提前輸出響應了,但是第二次請求的響應時間卻比請求傳送時間遲5秒。第二次請求的是b.php檔案,b.php檔案內容只有幾行**,為什麼會執行5秒才返回。
原因是,session是有鎖的。為防止併發的寫session資料,php自帶的的檔案儲存session資料是加了乙個互斥鎖。程式執行session_start(),此時當前程式就開始持有鎖。程式結束,此時程式自動釋放session的鎖。
瀏覽器第一次請求a.php檔案,對session檔案進行加鎖,雖然提前輸出響應,但程式還在執行,session檔案的鎖還未釋放。所以,第二次請求b.php檔案時,由於b.php檔案的開始就要開啟session檔案,但session檔案的鎖還未釋放,需要等待a.php執行完,也即要等待5秒。
一般session檔案跟session_id有關,每個session_id會建立乙個session檔案,下面可以看到兩次請求帶過去的session_id是一樣的。
a.php檔案請求sessid
b.php檔案請求sessid
如何解決session檔案加鎖的問題,可以使用session_write_close函式,該函式的作用就是資料寫入session檔案並結束會話。
修改a.php檔案,在使用session**後面加上session_write_close函式。
<?php
session_start();
$_session['uname'] = 'jianshu';
session_write_close();
............
瀏覽器執行index.html,檢視console日誌如下:
console日誌
發現沒有等待存在了。實際開發中,使用完session,可以加上session_write_close()函式,減少伺服器開銷。
php 後台執行,PHP開啟守護程序後台執行
只能在linux環境執行有時候難免要用到php守護程序,需要在cli模式下保持執行,直接一段 即可,linux php守護程序 啟動 停止 重啟 查詢狀態 class servicedeamon else else if pid 0 else else else else else echo pro...
Linux後台執行python程式,輸出日誌
實際開發時,會常常有需要執行很長時間的python程式,這時最佳策略就是將它放在linux伺服器後台執行,並且及時更新訊息。1 基礎命令 nohup python u py log 2 1 2 其他 只記錄錯誤資訊 nohup python u py dev null 2 error.log 2 1...
Linux將程式放在後台執行,關閉終端繼續執行
最近使用shell指令碼的形式執行任務,結果發現執行之後就一直在程式介面,ctrl c退出後程式終止,關閉終端後程式也退出,需要將程式交給linux去管理和執行,查詢了下資料 使用 nohup命令,具體如下 後台執行build.sh指令碼 nohup build.sh run build.sh的列印...