?
Ce document utilise Manuel du site Web PHP chinois Libérer
概括來說,fpm的實(shí)現(xiàn)就是創(chuàng)建一個master進(jìn)程,在master進(jìn)程中創(chuàng)建并監(jiān)聽socket,然后fork出多個子進(jìn)程,這些子進(jìn)程各自accept請求,子進(jìn)程的處理非常簡單,它在啟動后阻塞在accept上,有請求到達(dá)后開始讀取請求數(shù)據(jù),讀取完成后開始處理然后再返回,在這期間是不會接收其它請求的,也就是說fpm的子進(jìn)程同時只能響應(yīng)一個請求,只有把這個請求處理完成后才會accept下一個請求,這一點(diǎn)與nginx的事件驅(qū)動有很大的區(qū)別,nginx的子進(jìn)程通過epoll管理套接字,如果一個請求數(shù)據(jù)還未發(fā)送完成則會處理下一個請求,即一個進(jìn)程會同時連接多個請求,它是非阻塞的模型,只處理活躍的套接字。
fpm的master進(jìn)程與worker進(jìn)程之間不會直接進(jìn)行通信,master通過共享內(nèi)存獲取worker進(jìn)程的信息,比如worker進(jìn)程當(dāng)前狀態(tài)、已處理請求數(shù)等,當(dāng)master進(jìn)程要?dú)⒌粢粋€worker進(jìn)程時則通過發(fā)送信號的方式通知worker進(jìn)程。
fpm可以同時監(jiān)聽多個端口,每個端口對應(yīng)一個worker pool,而每個pool下對應(yīng)多個worker進(jìn)程,類似nginx中server概念。
在php-fpm.conf中通過[pool name]聲明一個worker pool:
[web1]listen = 127.0.0.1:9000...[web2]listen = 127.0.0.1:9001...
啟動fpm后查看進(jìn)程: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
具體實(shí)現(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; //當(dāng)前pool的worker鏈表 int running_children; //當(dāng)前pool的worker運(yùn)行總數(shù) int idle_spawn_rate; int warn_max_children; struct fpm_scoreboard_s *scoreboard; //記錄worker的運(yùn)行信息,比如空閑、忙碌worker數(shù) ... }