如何減少PHP-FPM的內存佔用

PHP-FPMPHPFastCGI過程管理器。在類Unix操作系統(包括Linux以及BSD系統)中,PHP-FPM通過安裝php5-fpm(Linux)或者php56-fpm(FreeBSD 10.1)來使用。

但是缺省安裝以及按照大量博客推薦安裝的PHP-FPM的最大問題是它會消耗大量資源,包括內存和CPU。本博客使用的服務器也遭遇了類似的命運。因爲我也是按照那些教程安裝的,而教程裏對於PHP-FPM的配置選項描述的不夠有效。

你可以在/etc/php5/fpm/pool.d目錄下發現這些低效的配置選項。舉例來說,以下是我的服務器(當然不是目前這個站點)上的那些低效選項:

; Choose how the process manager will control the number of child processes.
pm = dynamic
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500

那臺服務器是一臺DigitalOcean Droplet,配置512M內存。它上面運行了一個新網站,即使完全空閒時,也必須要靠交換內存才能避免僵死。執行top命令顯示了服務器上佔用內存最多的進程。

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
13891 cont      20     396944  56596  33416 S  0.0 11.3   :14.05 php5-fpm
13889 cont      20     396480  56316  32916 S  0.0 11.2   :17.67 php5-fpm
13887 cont      20     624212  55088  32008 S  0.0 11.0   :14.02 php5-fpm
13890 cont      20     396384  55032  32312 S  0.0 11.0   :13.39 php5-fpm
13888 cont      20     397056  54972  31988 S  0.0 11.0   :14.16 php5-fpm
14464 cont      20     397020  54696  31832 S  0.0 10.9   :09.44 php5-fpm
13892 cont      20     396640  54704  31936 S  0.0 10.9   :12.84 php5-fpm
 
13883 cont      20     396864  54692  31940 S  0.0 10.9   :15.64 php5-fpm
13893 cont      20     396860  54628  32004 S  0.0 10.9   :15.13 php5-fpm
13885 cont      20     396852  54412  32116 S  0.0 10.8   :13.94 php5-fpm
13884 cont      20     395164  53916  32364 S  0.0 10.7   :13.51 php5-fpm
13989 cont      20     394960  53548  32108 S  3.7 10.7   :14.37 php5-fpm
2778 mysql     20    1359152  31704   1728 S  0.7  6.3   1:38.80 mysqld
 
13849 root      20     373832   1180    188 S  0.0  0.2   :03.27 php5-fpm

輸出結果顯示有12php5-fpm子進程(用戶名是cont)和一個主進程(用戶名是root)。而這12個子進程只是呆坐在那裏,什麼事也不做,每個子進程白白消耗超過10%的內存。這些子進程主要是由pm=dynamic這個配置選項產生的。

老實說,絕大部分的雲主機擁有者也不知道所有這些配置選項是幹什麼用的,只是簡單地複製粘貼而已。我也不準備假裝我瞭解每個PHP配置文件裏的每一個選項的目的和意義。我在很大程度上也是複製粘貼的受害者。

但是我經常檢查服務器的資源佔用情況,困惑於爲什麼我的服務器佔用這麼多的內存和CPU。舉另外一個例子,是這臺服務器上的free -mt命令的結果:

              total       used       free     shared    buffers     cached
Mem:           490        480          9         31          6         79
-/+ buffers/cache:        393         96
Swap:         2047        491       1556
Total:        2538        971       1566

在沒有任何訪問量的情況下,也幾乎有整整1G的內存(實際內存加上交換內存)被佔用。當然,通過調整配置pm的數量可以有所改變,但只是輕微的。只要設置pm=dynamic,就會有空閒的子進程等在那裏等待被使用。

直到讀了一篇文章《A better way to run PHP-FPM》(更好地運行PHP-FPM)之後,我開始意識到應該如何修改我的配置文件。那篇文章是大約一年前寫的,令人失望的是我從昨天晚上搜索相關主題時纔看到它。如果你也有服務器並且使用PHP-FPM的話,我建議你好好讀一下那篇文章。

讀完文章之後,我修改了我的pm選項,如下:

; Choose how the process manager will control the number of child processes.
pm = ondemand
pm.max_children = 75
pm.process_idle_timeout = 10s
pm.max_requests = 500

最主要的改動就是用pm=ondemand替換了pm=dynamic。這一改動對資源佔用的影響是巨大的。下面是改動並重新加載php5-fpm之後運行free -mt的結果:

              total       used       free     shared    buffers     cached
Mem:           490        196        293         28          9         70
-/+ buffers/cache:        116        373
Swap:         2047        452       1595
Total:        2538        649       1888

和之前的結果對比,內存使用量下降了50%。產生這一下降的原因通過執行top命令一目瞭然:

 2778 mysql     20    1359152  56708   3384 S  0.0 11.3   2:11.06 mysqld                               
26896 root      20     373828  19000  13532 S  0.0  3.8   :02.42 php5-fpm                             25818 root      20      64208   4148   1492 S  0.0  0.8   :01.88 php5-fpm
25818 root      20      64208   4148   1492 S  0.0  0.8   :01.88 php5-fpm                            
17385 root      20      64208   4068   1416 S  0.0  0.8   :02.23 php5-fpm                              1465 ossec     20      15592   2960    480 S  0.0  0.6   :08.60 ossec-analysisd                      
 1500 root      20       6312   2072    328 S  0.0  0.4   :45.55 ossec-syscheckd                          1 root      20      33444   1940    812 S  0.0  0.4   :03.29 init
 

你注意到這裏已經沒有子進程了嗎?它們去哪裏了?這就是設置pm=ondemand的作用。這樣設置之後,只有當有需要的時候,子進程纔會被產生。事情做完之後,子進程會留在內存中10秒鐘時間(pm.process_idle_timeout = 10s),然後自己退出。

我只是對PHP-FPM的配置做了一點小小的修改,就節省了50%的內存。當然,這臺服務器沒有承受大併發的壓力,但我相信它能頂得住合理的高負載,考慮到它只有512M內存。再加上Nginx微緩存的配置,我想它會做的更好。當然還有另外一些PHP-FPMPercona MySQL的配置優化我還沒有做。這裏只是給大家分享一個我覺得非常有用的小竅門。

轉載地址: http://www.phpchina.com/portal.php?mod=view&aid=41247

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章