[TOC]
# php-fpm配置
PHP-FPM配置文件為php-fpm.conf,在這個配置文件中我們需要了解一些參數。下面所有的子進程均指php-fpm進程,可以在終端通過ps aux | grep php查看到。
* 顯示`php-fpm: pool www`的代表work子進程(實際處理請求)
* 顯示`php-fpm: process master`的代表master主進程(負責管理work子進程)
## 全局配置
先看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_timeout 子進程的空閑超時時間,如果超時時間到沒有新的請求可以服務,則會被殺死
**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左右,所以你需要根據自己的預期內存大小設定進程的數量。同時根據進程池的數量來看一個進程管理器的子進程數量限制。
## 測試平均PHP子進程占用的內存:
~~~
$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服務。
- OAuth
- 簡介
- 步驟
- 單點登錄
- .user.ini
- 時間轉換為今天昨天前天幾天前
- 獲取ip接口
- 協程
- 概念
- yield-from && return-values
- 協程與阻塞的思考
- 中間件
- mysqli異步與php的協程
- 代碼片段
- pdo 執行的sql語句
- 二進制安全
- 捕捉異常中斷
- global
- 利用cookie模擬登陸
- 解析非正常json
- 簡單的對稱加密算法
- RSA 加密
- 過濾掉emoji表情
- 判斷遠程圖片是否存在
- 一分鐘限制請求100次
- 文件處理
- 多文件上傳
- 顯示所有文件
- 文件下載和上面顯示所有文件配合
- 文件的刪除,統計,存數組等
- 圖片處理
- 簡介
- 驗證碼
- 圖片等比縮放
- 批量添加水印
- beanstalkd
- 安裝
- 使用
- RabbitMQ
- 簡介
- debain安裝
- centos安裝
- 常用方法
- 入門
- 工作隊列
- 訂閱,發布
- 路由
- 主題
- 遠程調用RPC
- 消息中間件的選型
- .htaccess
- isset、empty、if區別以及0、‘’、null
- php各版本
- php7.2 不向后兼容的改動
- php中的各種坑
- php7改變
- php慢日志
- 郵件
- PHPMailer實現發郵件
- 驗證郵件地址真實性
- 文件下載
- FastCgi 與 PHP-fpm 之間的關系
- openssl 加解密
- 反射
- 鉤子方法
- 查找插件
- opcode
- opcache使用
- opcache優化
- 分布式一致性hash算法
- 概念
- 哈希算法好壞的四個定義
- php實現
- java實現
- 數組
- jwt
- jwt簡介
- 單點登錄
- phpize
- GeoIP擴展
- php無法獲得https網頁內容的解決方案
- homestead運行的腳本
- Unicode和Utf-8轉換
- php優化
- kafka
- fpm配置
- configure配置詳解