PHP-FPM
先來了解一些名詞概念:php
CGI
是Common Gateway Interface(通用網管協議)
,用於讓交互程序和Web服務器通訊的協議。它負責處理URL的請求,啓動一個進程,將客戶端發送的數據做爲輸入,由Web服務器收集程序的輸出並加上合適的頭部,再發送回客戶端。html
FastCGI
是基於CGI
的加強版本的協議,不一樣於建立新的進程來服務請求,使用持續的進程和建立的子進程來處理一連串的進程,這些進程由FastCGI服務器管理,開銷更小,效率更高。緩存
PHP-FPM
是PHP
實現的FastCGI Process Manager(FastCGI進程管理器)
, 用於替換PHP FastCGI
的大部分附加功能,適用於高負載網站。支持的功能如:安全
PHP-FPM
在5.4以後已經整合進入PHP源代碼中,提供更好的PHP進程管理方式,能夠有效控制內存和進程,平滑重載PHP配置。若是須要使用,在./configure
的時候帶上-enable-fpm
參數便可,使用PHP-FPM
來控制FastCGI
進程:服務器
// 支持start/stop/quit/restart/reload/logrotate參數 // quit/reload是平滑終止和平滑從新加載,即等現有的服務完成 ./php-fpm --start
PHP-FPM
配置PHP-FPM
配置文件爲php-fpm.conf
,在這個配置文件中咱們須要瞭解一些參數。下面全部的子進程均指php-fpm
進程,能夠在終端經過ps aux | grep php
查看到。socket
php-fpm: pool www
的表明work子進程(實際處理請求)php-fpm: process master
的表明master主進程(負責管理work子進程)先看PHP-FPM
最重要的全局配置部分:php-fpm
emergency_restart_threshold
若是在emergency_restart_interval
設定的時間內收到該參數設定次數的SIGSEGV
或SIGBUS
退出的信號,則FPM
會從新啓動。默認值爲0,表示關閉該功能。測試
emergency_restart_interval
設定平滑重啓的間隔時間,有助於解決加速器中共享內存的使用問題。可用單位s(默認)/m/h/d
,默認值爲0, 表示關閉。優化
process.max
FPM
可以建立的最大子進程數量,它在使用多個pm = dynamic
配置的php-fpm pool
進程池的時候,控制全局的子進程數量。默認值爲0,表明着無限制。網站
PHP-FPM
的配置其他部分是一個名爲Pool Definitions
的區域,這個區域的配置設置每一個PHP-FPM
進程池,進程池中是一系列相關的子進程。這部分開頭都是[進程池名稱]
,如[www]
。
此時能夠解釋看到ps aux | grep php
中顯示的是php-fpm: pool www
。
pm
pm
指的是process manager
,指定進程管理器如何控制子進程的數量,它爲必填項,支持3個值:
static
: 使用固定的子進程數量,由pm.max_children
指定dynamic
:基於下面的參數動態的調整子進程的數量,至少有一個子進程
pm.max_chidren
: 能夠同時存活的子進程的最大數量pm.start_servers
: 啓動時建立的子進程數量,默認值爲min_spare_servers + max_spare_servers - min_spare_servers) / 2
pm.min_spare_servers
: 空閒狀態的子進程的最小數量,若是不足,新的子進程會被自動建立pm.max_spare_servers
: 空閒狀態的子進程的最大數量,若是超過,一些子進程會被殺死ondemand
: 啓動時不會建立子進程,當新的請求到達時才建立。會使用下面兩個參數:
pm.max_children
pm.process_idle_timeou
t 子進程的空閒超時時間,若是超時時間到沒有新的請求能夠服務,則會被殺死pm.max_requests
每個子進程的最大請求服務數量,若是超過了這個值,該子進程會被自動重啓。在解決第三方庫的內存泄漏問題時,這個參數會頗有用。默認值爲0,指子進程能夠持續不斷的服務請求。
PHP-FPM
配置優化PHP-FPM
管理的方式是一個master
主進程,多個pool
進程池,多個worker
子進程。其中每一個進程池監聽一個socket
套接字。具體的圖示:
其中的worker
子進程實際處理鏈接請求,master
主進程負責管理子進程:
1. `master`進程,設置1s定時器,經過`socket`文件監聽 2. 在`pm=dynamic`時,若是`idle worker`數量<`pm.min_spare_servers`,建立新的子進程 3. 在`pm=dynamic`時,若是`idle worker`數量>`pm.max_spare_servers`,殺死多餘的空閒子進程 4. 在`pm=ondemand`時,若是`idle worker`空閒時間>`pm.process_idle_timeout`,殺死該空閒進程 5. 當鏈接到達時,檢測若是`worker`數量>`pm.max_children`,打印`warning`日誌,退出;若是無異常,使用`idle worker`服務,或者新建`worker`服務
咱們爲了不PHP-FPM
主進程因爲某些糟糕的PHP代碼掛掉,須要設置重啓的全局配置:
; 若是在1min內有10個子進程被中斷失效,重啓主進程 emergency_restart_threshold = 10 emergency_restart_interval = 1m
每個子進程同時只能服務一次鏈接,因此控制同時存在多少個進程數就很重要,若是過少會致使不少沒必要要的重建和銷燬的開銷,若是過多又會佔用過多的內存,影響其餘服務使用。
咱們應該測試本身的PHP進程使用多少內存,通常來講剛啓動時是8M左右,運行一段時間因爲內存泄漏和緩存會上漲到30M左右,因此你須要根據本身的預期內存大小設定進程的數量。同時根據進程池的數量來看一個進程管理器的子進程數量限制。
$ps auxf | grep php | grep -v grep work 26829 0.0 0.0 715976 4712 ? Ss Jul11 0:00 php-fpm: master process (./etc/php-fpm.conf) work 21889 0.0 0.0 729076 29668 ? S 03:12 0:20 \_ php-fpm: pool www work 21273 0.0 0.0 728928 31380 ? S 03:25 0:21 \_ php-fpm: pool www work 15114 0.0 0.0 728052 29084 ? S 03:40 0:19 \_ php-fpm: pool www work 17072 0.0 0.0 728800 34240 ? S 03:54 0:22 \_ php-fpm: pool www work 22763 0.0 0.0 727904 20352 ? S 11:29 0:04 \_ php-fpm: pool www work 38545 0.0 0.0 727796 19484 ? S 12:34 0:01 \_ php-fpm: pool www // 共佔用的內存數量 $ps auxf | grep php | grep -v grep | grep -v master | awk '{sum+=$6} END {print sum}' 162712 // 全部的子進程數量 $ ps auxf | grep php | grep -v grep | grep -v master | wc -l 6
能夠看到第6列,每個子進程的內存佔用大概在19-34M之間(單位爲KB)。平均的內存佔用爲162712KB/6 = 27.1M
。
$ free -g total used free shared buffers cached Mem: 157 141 15 0 4 123 -/+ buffers/cache: 13 143 Swap: 0 0 0
能夠看出個人服務器總得內存大小是157G(-g採用了G的單位)。
此時若是咱們分配所有的內存給PHP-FPM
使用,那麼進程數能夠限制在157000/27 = 5814
,可是因爲個人服務器同時服務了不少內容,因此咱們能夠向下調整到512個進程數:
process.max = 512 pm = dynamic pm.max_children = 512 pm.start_servers = 16 pm.min_spare_servers = 8 pm.max_spare_serveres = 30
因爲糟糕的插件和庫,內存泄漏時有發生,因此咱們須要對每個子進程服務的請求數量作限制,防止無限制的內存泄漏:
pm.max_requests = 1000
若是上面的配置都按照你的實際需求和環境配置好了,不要忘記重啓PHP-FPM
服務。