一、問題現象
二、專案背景
- 線上web服務是nginx+php7+mysql
- 線上伺服器配置:8核16G
-
php-fpm配置:
pm = static pm.max_children = 500 ;pm.max_requests = 5000 //此配置沒有開啟
三、記憶體持續增高原因分析
- 檢視了php-fpm相關配置後,發現系統是靜態機制,並且沒有配置max_requests項,沒有退出機制
- php程式長期存在導致記憶體積壓無法釋放,所以記憶體消耗持續升高
-
nginx+php-fpm執行原理?【https://juejin.im/post/58db7d...】
cgi、fast-cgi、php-fpm之間的關係? 我的理解: 1.webserver最開始只能處理靜態請求,後來出現了動態請求,比如php程式,然而webserver是無法處理php程式的,這個是時候怎麼辦? 2.交給php直譯器來處理動態php請求 3.那麼webserver可以將動態請求交給php直譯器處理,那麼webserver如何與php直譯器進行通訊呢?【webserver就是nginx/apache】 4.這個時候就出現了cgi,cgi協議就是webserver和php直譯器進行通訊的協議 5.webserver在每次請求過來都會fork一個cgi程式進行處理,處理完成後返回,如果有10k請求,那麼就fork 10k個程式,顯然對系統資源很浪費 6.這時對cgi做了優化,出現了fast-cgi,fast-cgi在請求處理完成後不會直接kill掉這個程式,而是繼續保留請求下一次請求,這樣一個程式就能處理多個請求,不用每次都fork程式減少了系統資源浪費 7.而php-fpm就是fast-cgi的實現,並且提供了程式管理的功能,包含master和worker兩種型別的程式 8.master程式只負責監聽埠,接收來自webserver的請求,worker程式有多個,每個worker程式內部都嵌入了一個php直譯器,是php程式碼真正執行的地方
-
一些php-fpm引數理解:
pm = dynamic # 三種型別選擇,static/dynamic/ondemand pm.max_children = 5 # php-fpm的worker程式最大數量 pm.start_servers = 3 # php-fpm啟動時候,啟動的worker數量 pm.min_spare_servers = 2 # php-fpm最小空閒程式數量,每時每刻最少也有2個是空閒的程式 pm.max_spare_servers = 4 # php-fpm最大的空閒程式數量 pm.max_requests = 200 # 單個程式處理請求數量達到200就會kill掉該程式重啟,程式一直存活容易發生記憶體洩漏
四、解決方案
- 通過現在php-fpm的配置可以得知,php-fpm沒有設定max_requests,代表程式一直不會退出,每個請求完成後php-cgi會回收記憶體,但是不會釋放給作業系統,所以大量記憶體被php-cgi佔用。
- 官方的解決辦法就是降低PHP_FCGI_MAX_REQUESTS的值,對應php-fpm配置中的max_requests
-
所以,只要重新設定 max_requests 的值,讓程式達到這個值後自動重啟釋放記憶體即可
# php-fpm.conf配置 pm = static pm.max_children = 500 pm.start.servers = 100 pm.min_spare_servers = 20 pm.max_spare_servers = 100 pm.max_requests = 2000
-
修改完配置後對php-fpm進行重啟
//查詢當前fpm的master程式號 ps aux|grep php-fpm | grep master //平滑重啟fpm,42891是master程式號 kill -USR2 42891 //立即終止fpm kill -QUIT 42891 //檢視狀態 ps aux|grep php-fpm //備註: php 5.3.3 以後的php-fpm 不再支援 php-fpm 以前具有的 /usr/local/php/sbin/php-fpm (start|stop|reload)等命令,所以不要再看這種老掉牙的命令了,需要使用訊號控制: master程式可以理解以下訊號 INT, TERM 立刻終止 QUIT 平滑終止 USR1 重新開啟日誌檔案 USR2 平滑過載所有worker程式並重新載入配置和二進位制模組
- 參考:https://www.cnblogs.com/cocol...