?
This document uses PHP Chinese website manual Release
概括來說,fpm的實現(xiàn)就是創(chuàng)建一個master進程,在master進程中創(chuàng)建并監(jiān)聽socket,然后fork出多個子進程,這些子進程各自accept請求,子進程的處理非常簡單,它在啟動后阻塞在accept上,有請求到達后開始讀取請求數(shù)據(jù),讀取完成后開始處理然后再返回,在這期間是不會接收其它請求的,也就是說fpm的子進程同時只能響應(yīng)一個請求,只有把這個請求處理完成后才會accept下一個請求,這一點與nginx的事件驅(qū)動有很大的區(qū)別,nginx的子進程通過epoll管理套接字,如果一個請求數(shù)據(jù)還未發(fā)送完成則會處理下一個請求,即一個進程會同時連接多個請求,它是非阻塞的模型,只處理活躍的套接字。
fpm的master進程與worker進程之間不會直接進行通信,master通過共享內(nèi)存獲取worker進程的信息,比如worker進程當前狀態(tài)、已處理請求數(shù)等,當master進程要殺掉一個worker進程時則通過發(fā)送信號的方式通知worker進程。
fpm可以同時監(jiān)聽多個端口,每個端口對應(yīng)一個worker pool,而每個pool下對應(yīng)多個worker進程,類似nginx中server概念。
在php-fpm.conf中通過[pool name]聲明一個worker pool:
[web1]listen = 127.0.0.1:9000...[web2]listen = 127.0.0.1:9001...
啟動fpm后查看進程:ps -aux|grep fpm
root 27155 0.0 0.1 144704 2720 ? Ss 15:16 0:00 php-fpm: master process (/usr/local/php7/etc/php-fpm.conf) nobody 27156 0.0 0.1 144676 2416 ? S 15:16 0:00 php-fpm: pool web1 nobody 27157 0.0 0.1 144676 2416 ? S 15:16 0:00 php-fpm: pool web1 nobody 27159 0.0 0.1 144680 2376 ? S 15:16 0:00 php-fpm: pool web2 nobody 27160 0.0 0.1 144680 2376 ? S 15:16 0:00 php-fpm: pool web2
具體實現(xiàn)上worker pool通過fpm_worker_pool_s這個結(jié)構(gòu)表示,多個worker pool組成一個單鏈表:
struct fpm_worker_pool_s { struct fpm_worker_pool_s *next; //指向下一個worker pool struct fpm_worker_pool_config_s *config; //conf配置:pm、max_children、start_servers... int listening_socket; //監(jiān)聽的套接字 ... //以下這個值用于master定時檢查、記錄worker數(shù) struct fpm_child_s *children; //當前pool的worker鏈表 int running_children; //當前pool的worker運行總數(shù) int idle_spawn_rate; int warn_max_children; struct fpm_scoreboard_s *scoreboard; //記錄worker的運行信息,比如空閑、忙碌worker數(shù) ... }