1. 程式人生 > >nginx+php-fpm模式php記憶體洩漏探究

nginx+php-fpm模式php記憶體洩漏探究

之前遇到過一次伺服器記憶體告警,檢視後發現有個php-fpm程序佔用了2G的記憶體。但我明明在php.ini檔案裡面,有配置 memory_limit = 256M,那為什麼會有佔用2G記憶體的php-fpm程序呢?

這裡先簡單說一下nginx+php-fpm模式的工作原理。 


nginx伺服器fork出n個子程序(worker),php-fpm管理器fork出n個子程序。
當有使用者請求,nginx的一個worker接收請求,並將請求拋到socket中。
php-fpm空閒的子程序監聽到socket中有請求,接收並處理請求。
這裡要重點說一下第三步驟。第三步涉及到php-fpm程序生命週期的東西。一個php-fpm的生命週期大致是這樣的:模組初始化(MINIT)-> 模組啟用(RINIT)-> 請求處理 -> 模組停用(RSHUTDOWN) -> 模組啟用(RINIT)-> 請求處理 -> 模組停用(RSHUTDOWN)……. 模組啟用(RINIT)-> 請求處理 -> 模組停用(RSHUTDOWN)-> 模組關閉(MSHUTDOWN)。在一個php-fpm程序的生命週期裡,會有多次的模組啟用(RINIT)-> 請求處理 -> 模組停用(RSHUTDOWN)的過程。這個“請求處理”的大致過程是這樣的:php讀取相應的php檔案,對其進行詞法分析,生成opcode,zend虛擬機器執行opcode。

回到一開始說的PHP配置檔案裡面的memory_limit 這個東西,其實,它限制的只是這個“請求處理”的記憶體。所以,這個引數跟php-fpm程序佔用的記憶體並沒有什麼關係。那為什麼會有佔用2G大小的php-fpm程序呢?原因是這樣的:php是用c寫的,所以,難免又會一些記憶體洩露。也就是說,在“請求處理”這個過程結束後,有些變數沒有被銷燬,然後就導致一個php-fpm程序佔用的記憶體越來越大。

那麼,有什麼辦法能阻止這個問題呢?方法一:寫不洩漏記憶體的php程式;方法二:在php-fpm配置檔案中,將pm.max_requests這個引數設定小一點。這個引數的含義是:一個php-fpm子程序最多處理pm.max_requests個使用者請求後,就會被銷燬。當一個php-fpm程序被銷燬後,它所佔用的所有記憶體都會被回收。

以下是我自己做的一次測試:

首先:將php-fpm.conf裡面pm.max_chindren引數設為1。這意味著,php-fpm管理器只會fork出一個php-fpm子程序。這樣一來,使用者的每次請求,都會讓這個程序來處理。然後隨便請求我自己的網站,會看到有如下結果: 
 
可以看到,那個php-fpm子程序佔用的記憶體越來越大。

然後我將php-fpm重啟一下: 
 
可以看到php-fpm子程序佔用的記憶體立刻變小了。

最後我將pm.max_requests這個引數設為5,然後再隨便請求幾次我的網站,看一下結果: 
 
可以看到,php-fpm子程序的程序id會自動變化。這說明,php-fpm子程序確實會自動被銷燬,然後再產生新的php-fpm子程序,而且php-fpm子程序佔用的記憶體也沒有越來越大。
--------------------- 
原文:https://blog.csdn.net/blakefez/article/details/46691171 
版權宣告:本文為博主原創文章,轉載請附上博文連結!