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

來源:互聯網
上載者:User

這篇文章主要介紹了關於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,完成實際商務邏輯。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.