首頁 >後端開發 >php教程 >PHP記憶體溢位、命令列和Web服務兩種執行方式的理解

PHP記憶體溢位、命令列和Web服務兩種執行方式的理解

不言
不言原創
2018-05-31 16:53:252073瀏覽

這篇文章主要介紹了關於PHP記憶體溢出、命令列和Web服務兩種執行方式的理解,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

#開發過程中,某個介面由於從資料庫讀取資料量過大,回傳狀態為200,但無回應數據,PHP錯誤日誌裡有下列資訊:PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted。

很明顯這是記憶體溢出(Out Of Memory)引發的錯誤,但是令我疑惑的是,Yii 框架的業務日誌(application.log)裡沒有任何輸出,頁面上也沒有Stack Trace 的錯誤訊息,於是對這個原因進行追查。

原因如下,先看Yii 框架CApplication.php 檔案核心程式碼:

public function run()
{    if($this->hasEventHandler('onBeginRequest'))        
$this->onBeginRequest(new CEvent($this));
    register_shutdown_function(array($this,'end'),0,false);    
    $this->processRequest();    
    if($this->hasEventHandler('onEndRequest'))        
    $this->onEndRequest(new CEvent($this));
}

在處理請求前使用了register_shutdown_function 註冊異常終止時的回調,正常來說,PHP 出現異常腳本終止時會回呼end() 方法,在onEndRequest 事件的監聽器中可以使用error_get_last() 取得到本次錯誤。

但是,當OOM 發生時,Linux Out Of Memory killer 會執行kill -9 發送SIGKILL 訊號,根據PHP 手冊中的說明, SIGKILL 訊號無法擷取和攔截,PHP 腳本會直接退出,任何清除程式碼都不會執行,所以register_shutdown_function 方法不會發揮作用,自然也不會有後續的日誌記錄、錯誤頁面顯示等流程。

另外在開發中註意到一個現象:透過 Web 存取會出現 OOM,但透過 Console 執行就不會報錯。

由此可見兩種方式是有差別的,Web 存取時,PHP 腳本進程由PHP-FPM啟動,還要受FPM 設定檔限制,/etc/php-fpm.d裡設定檔有php_admin_value[memory_limit] = 128M 限制。所以透過 Web 存取時,僅增加 php.ini 中的 memory_limit 無效。

而Console 方式執行不經過PHP-FPM,所以僅受php.ini 中配置的記憶體參數限制,而開發機中配置的memory_limit => 512M => 512M,所以此時不會產生OOM。

這裡有個疑問,從實作原理的角度,PHP-FPM 是如何對 PHP 流程管理的? PHP-FPM 真的會用 kill -9 殺死 PHP 腳本進程麼?


附上WebServer、PHP-FPM、PHP 腳本的呼叫關係:

要求先進入Web 伺服器(如Nginx),Nginx 分發請求(依據server節點、location節點等設定):

  1. 請求靜態資源不需要FastCGI 處理,直接轉到對應檔案位置

  2. ##動態請求需要PHP 程式碼處理,則需要把請求交給實作了FastCGI 協定的程式(PHP-FPM)

可以在Nginx看到這樣的設定資訊:「fastcgi_pass 127.0.0.1:9000 ;”,執行指令“lsof -i:9000”可以看到9000埠剛好是PHP-FPM進程。

Nginx 將請求資訊傳給了PHP-FPM,PHP-FPM 分配一個Worker 進程處理,Worker 進程註冊變數

$_GET/$_POST 等,根據請求資訊存取指定的PHP腳本文件,然後使用PHP 解釋器執行。 (我的理解是:相當於PHP-FPM 啟動了PHP 解釋器,有點像執行了
php -f script.php 指令)

網路請求的資訊層層傳遞,最終到達PHP,所以在PHP 程式碼裡可以取得到本次HTTP 請求的各種參數。

執行哪個PHP 腳本由Nginx 告訴PHP-FPM,在Nginx 配置中可見一行:

fastcgi_param SCRIPT_FILENAME /home/dev_user/www/xxx/webroot/index.php;

若不指定PHP 文件,就會使用該預設配置,嘗試使用根目錄下的index.php 檔案。 index.php 裡會啟動框架程序,由框架找到對應的 Controller 和 Action,完成實際業務邏輯。

以上是PHP記憶體溢位、命令列和Web服務兩種執行方式的理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn