原文地址:https://blog.csdn.net/lzx_victory/article/details/85917161
PHP-FPM模式相對於CLI比較復雜,因為PHP-FPM為常駐進程不斷處理請求,因此二者只是在執行流程略有不同.
PHP-FPM
現在PHP廣泛被使用的一種模式,用於解析FastCGI協議,執行相應的請求.
PHP-FPM 三種模式
static
FPM啟動根據pm.max_children固定的woker進程數.
dynamic
FPM是啟動的woker進程是變化:根據參數pm.start_servers~pm.max_children之間的.
pm.min_spare_servers~pm.min_spare_servers指明可空閑進程的個數,空閑進程數超過pm.min_spare_servers就會被kill掉.
ondemand
啟動時不分配Woker進程,根據pm.process_idle_timeout空閑時間后會把進程kil掉.也受到pm.max_children的限制.
其余參數設置
pm.max_requests = 1000 #設置每個子進程重生之前服務的請求數. 對於可能存在內存泄漏的第三方模塊來說是非常有用. 如果設置為 '0' 則一直接受請求. 等同於 PHP_FCGI_MAX_REQUESTS 環境變量. 默認值: 0. pm.status_path = /status #FPM狀態頁面的網址. 如果沒有設置, 則無法訪問狀態頁面. 默認值: none. munin監控會使用到 rlimit_files = 1024 #設置文件打開描述符的rlimit限制. 默認值: 系統定義值默認可打開句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。
Frok流程
當PHP-FPM啟動后calling process會fork master進程,然后Fork worker.
Worker: 實際處理請求的進程.
Master: 管理worker進程,對worker進程重啟,關閉等操作.

Master進程
Master通過監聽"外部信號"與Woker進程的信號(SIGHLD:Woker進程發送信號,Master進程處理善后工作,然后在按照模式啟動),對相應的信號來管理Worker進程.
信號機制:Master采用了socketpair一端寫入信號事件,另一端在注冊到事件機制中,在Master Loop讀取事件,調用回調函數(fpm_got_signal)執行對應的信號.
FPM內部對事件進行了封裝,用於支持不同的事件模型,例如epoll,select,kqueue等.
Master進程還有重要的作用統計所有Worker進程的信息,用於統計的數據結構叫做計分板.
Woker進程
Woker進程,特殊處理的信號只有SIGQUIT,其余的都是執行默認信號處理(SIG_DFL).
當收到SIGQUIT時,in_shutdown靜態全局變量置為1,確保在fcgi_accept_request方法返回-1,不在accept新的請求並結束相應的Woker進程.
每個Woker進程存在於一個進程池內,根據FPM可以配置多個進程池.
每個Worker進程進行accept時會阻塞並接收一個請求.每個Woker進程執行accept函數在Linux2.6內核版本不會形成驚群效應.
FCGI協議
FCGI是一種交互式協議,基於CGI協議的一種變體.在每次請求到達是不需要新建進程,減少了進程創建以及銷毀的資源損耗.
每次FastCGI請求成為Record由以下結構組成:
BeginRequestRecord:包含請求的信息,請求ID,以及請求的角色等.
EndRequestBody:請求結束的標識,包含最終Appliancation返回處理狀態.
Header:被包含EndRequestBody,BeginRequestRecord,以及以及類型當中.每個數據段需要由Header指定這個段的類型,RequestID以及長度…
/* * Values for type component of FCGI_Header */ #define FCGI_BEGIN_REQUEST 1 #define FCGI_ABORT_REQUEST 2 #define FCGI_END_REQUEST 3 #define FCGI_PARAMS 4//key value 類型. #define FCGI_STDIN 5 #define FCGI_STDOUT 6 #define FCGI_STDERR 7 #define FCGI_DATA 8 #define FCGI_GET_VALUES 9 #define FCGI_GET_VALUES_RESULT 10 #define FCGI_UNKNOWN_TYPE 11 #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE) typedef struct { unsigned char version; unsigned char type; unsigned char requestIdB1; unsigned char requestIdB0; unsigned char contentLengthB1; unsigned char contentLengthB0; unsigned char paddingLength; unsigned char reserved; } FCGI_Header;
FCGI協議詳述,這里有詳細的介紹以及示例.
CLI 與 PHP-FPM執行流程
PHP-FPM

CLI
CLI也是最常用的一種模式,我們來看下他執行的過程.

1.php_module_start_up:將sapi_globals中的成員變量進行初始化.
2.php_request_start_up:將zend引擎的編譯器,掃描器,編譯器等進行初始化.
3.php_excute_script:讀取代碼並掃描詞法和語法生成AST,初始化op_array並將AST編譯生成opcode,設置op_array對應的handler,然后執行opcode.
4.php_request_shutdown:調用各模塊的析構函數,輸出緩沖區調用擴展的RSHUTDOWN函數.銷毀全局變量,關閉解析器.
5.php_module_shutdown:在php_module_startup初始化的內容要進行銷毀.
