PHP-FPM
是PHP
的FastCGI
過程管理器。在類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
輸出結果顯示有12
個php5-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-FPM
和Percona
MySQL
的配置優化我還沒有做。這裏只是給大家分享一個我覺得非常有用的小竅門。
轉載地址: http://www.phpchina.com/portal.php?mod=view&aid=41247