[TOC]
:-: 
## 簡介
**PHP-FPM**(FastCGI 進程管理器)用于替換 PHP FastCGI 的大部分附加功能,對于高負載網站是非常有用的。
它的功能包括:
* 支持平滑停止/啟動的高級進程管理功能;
* 可以工作于不同的 uid/gid/chroot 環境下,并監聽不同的端口和使用不同的 php.ini 配置文件(可取代 `safe_mode` 的設置);
* stdout 和 stderr 日志記錄;
* 在發生意外情況的時候能夠重新啟動并緩存被破壞的 opcode;
* 文件上傳優化支持;
* "慢日志" - 記錄腳本(不僅記錄文件名,還記錄 PHP backtrace 信息,可以使用 ptrace或者類似工具讀取和分析遠程進程的運行數據)運行所導致的異常緩慢;
* `fastcgi_finish_request()` - 特殊功能:用于在請求完成和刷新數據后,繼續在后臺執行耗時的工作(錄入視頻轉換、統計處理等);
* 動態/靜態子進程產生;
* 基本 SAPI 運行狀態信息(類似 Apache 的 mod_status);
* 基于 php.ini 的配置文件。
## 工作原理
php-fpm啟動 -> 生成 n 個 fast-cgi 協議處理進程 -> 監聽一個端口等待任務
用戶請求 -> web 服務器接收請求 -> 請求轉發給 php-fpm -> php-fpm 交給一個空閑進程處理 -> 進程處理完成 -> php-fpm 返回給 web 服務器 -> web服務器接收數據 -> 返回給用戶
## 工作模式
php-fpm 進程管理一共有三種模式:ondemand、static、dynamic。
php-fpm 的工作模式和 nginx 類似,都是一個 master,多個 worker 模型。每個 worker 都在 accept 本 pool 內的監聽套接字。
### 靜態模式 **static**
php-fpm 啟動時采用固定大小數量的worker,在運行期間也不會擴容,雖然也有1秒的定時器,僅限于統計一些狀態信息,例如空閑worker個數,活動worker個數,網絡連接隊列長度等信息。
php-fpm.conf:
~~~text
[test]
listen = 127.0.01:9000
pm = static
pm.max_children = 40 # 大于0 ,必須配置,且只有這一個參數生效
~~~
### 動態模式 **dynamic**
在 php-fpm 啟動時,會初始啟動一些 worker,在運行過程中動態調整 worke 數量,worke r的數量受限于pm.max_children 配置,同時受限全局配置 process.max 。
~~~text
[test]
listen = 127.0.01:9000
pm = dynamic
pm.max_children = 10 # 大于 0
pm.start_servers = 2 # 有效范圍 [pm.min_spare_servers, pm.max_spare_servers] 如果沒有配置,默認pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2
pm.min_spare_servers = 1 # <= pm.max_spare_servers
pm.max_spare_servers = 6
~~~
#### 原理
初始啟動 `pm.min_spare_servers` 個 worker,而最大子進程數則由 `pm.max_children` 去控制,閑置的子進程數則由`pm.min_spare_servers`和`pm.max_spare_servers`控制,如果閑置的子進程超出了`pm.max_spare_servers`,則會被殺掉。master 進程中設置了 1秒定時器,檢查空閑 worker 數量,按照一定策略動態調整 worker 數量,增加或減少。
#### 優缺點
- 優點:動態擴容,不浪費系統資源,master進程設置的1秒定時器對系統的影響忽略不計;
- 缺點:如果所有worker都在工作,新的請求到來只能等待master在1秒定時器內再新建一個worker,這時可能最長等待1s;
### 按需分配 **ondemand**
在 php-fpm 啟動的時候,不會給這個 pool 啟動任何一個 worker,是按需啟動,當有連接過來才會啟動。
~~~text
[test]
listen = 127.0.01:9000
pm = ondemand
pm.process_idle_timeout = 60 # 大于0,如果不設置,默認10s
pm.max_children = 10 # 大于0
~~~
#### 原理
新建 worker 的觸發條件是連接的到來,而不是實際的請求(只進行連接比如 telnet,不發請求數據也會新建 worker)
worker 的數量受限于 `pm.max_children` 配置,同時受限全局配置 `process.max`
master 進程中 1秒定時器會找到空閑 worker ,如果空閑時間超所 `pm.process_idle_timeout` ,則關閉,這個機制可能會關閉所有的 worker。
#### 優缺點
- 優點:按流量需求創建,不浪費系統資源(在硬件如此便宜的時代,這個優點略顯雞肋)
- 缺點:由于 php-fpm 是短連接的,所以每次請求都會先建立連接,所以,在大流量的系統上 master 進程會變得繁忙,占用系統 cpu 資源,不適合大流量環境的部署
## PHP-fpm 與 Nginx 的通信方式
### **unix socket**
* nginx 方面需要指定`fastcgi_pass unix:/xxx/xxx/xxx.sock`,如:
~~~text
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;;
fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index index.php;
}
~~~
* 相應地,php-fpm 方面需要指定`listen = /xxx/xxx/xxx.sock`,如:
~~~text
listen = /var/run/php-fpm.sock
~~~
### **tcp socket**
* nginx 方面需要指定`fastcgi_pass ip:port`,如:
~~~text
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}
~~~
* 相應地,php-fpm 方面需要指定`listen = ip:port`,如:
~~~json
listen = 127.0.0.1:9000
~~~
帶有權重的集群:
~~~json
upstream api_fpm {
server ip1:port1 weight=x1;
server ip2:port2 weight=x2;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;;
fastcgi_pass api_fpm;
fastcgi_index index.php;
}
~~~
### 對比
* `unix socket`基于本地`.sock`文件通信,省去底層網絡協議傳輸的消耗,更高效。
* `tcp socket`配合`nginx 的 upstream`實現了集群部署,更利于水平擴展。
* 基于上述特點:
* 不需要集群,追求快速影響時,選擇`unix socket`。
* 更注重服務穩定性和可擴展性時,選擇`tcp socket`。
- PHP
- PHP 核心架構
- PHP 生命周期
- PHP-FPM 詳解
- PHP-FPM 配置優化
- PHP 命名空間和自動加載
- PHP 運行模式
- PHP 的 Buffer(緩沖區)
- php.ini 配置文件參數優化
- 常見面試題
- 常用函數
- 幾種排序算法
- PHP - 框架
- Laravel
- Laravel 生命周期
- ThinkPHP
- MySQL
- 常見問題
- MySQL 索引
- 事務
- 鎖機制
- Explain 使用分析
- MySQL 高性能優化規范
- UNION 與 UNION ALL
- MySQL報錯:sql_mode=only_full_group_by
- MySQL 默認的 sql_mode 詳解
- 正則表達式
- Redis
- Redis 知識
- 持久化
- 主從復制、哨兵、集群
- Redis 緩存擊穿、穿透、雪崩
- Redis 分布式鎖
- RedisBloom
- 網絡
- 計算機網絡模型
- TCP
- UDP
- HTTP
- HTTPS
- WebSocket
- 常見幾種網絡攻擊方式
- Nginx
- 狀態碼
- 配置文件
- Nginx 代理+負載均衡
- Nginx 緩存
- Nginx 優化
- Nginx 配置 SSL 證書
- Linux
- 常用命令
- Vim 常用操作命令
- Supervisor 進程管理
- CentOS與Ubuntu系統區別
- Java
- 消息隊列
- 運維
- RAID 磁盤陣列
- 邏輯分區管理 LVM
- 業務
- 標準通信接口設計
- 業務邏輯開發套路的三板斧
- 微信小程序登錄流程
- 7種Web實時消息推送方案
- 用戶簽到
- 用戶注冊-短信驗證碼
- SQLServer 刪除同一天用戶重復簽到
- 軟件研發完整流程
- 前端
- Redux
- 其他
- 百度云盤大文件下載
- 日常報錯記錄
- GIT
- SSL certificate problem: unable to get local issuer certificate
- NPM
- reason: connect ECONNREFUSED 127.0.0.1:31181
- SVN
- SVN客戶端無法連接SVN服務器,主機積極拒絕
- Python
- 基礎
- pyecharts圖表
- 對象
- 數據庫
- PySpark
- 多線程
- 正則
- Hadoop
- 概述
- HDFS