㈠ php-fpm的文檔
php-fpm 已經在 linux、MacOSX、Solaris 和 FreeBSD 上測試通過。
確信 libxml2(在某些系統上叫做libxml2-devel)已經安裝。
下載最小的 php 和php-fpm
$ bzip2 -cdphp-5.2.5.——tar.——bz2 | tar xf -
$ gzip -cdphp-5.2.5-fpm-0.5.7.diff.gz | patch -d php-5.2.5 -p1
$ cdphp-5.2.5 && ./configure --enable-fastcgi--enable-fpm
$ make all install
編輯 $prefix/etc/php-fpm.conf
運行 $prefix/bin/php-cgi --fpm
仔細檢查 $prefix/logs/php-fpm.log
運行phpinfo() 檢查你的網站是否還正常運行
master 進程的 pid 被存放在 $prefix/logs/php-fpm.pid
master進程可以理解以下信號: SIGINT, SIGTERM 立刻終止 SIGQUIT 平滑終止 SIGUSR1 重新打開日誌文件 SIGUSR2 平滑重載所有worker進程並重新載入配置和二進制模
㈡ 如何用supervisor守護php-fpm主進程以實現php-fpm的自動重啟
1. 安裝supervisor
supervisor本身是python實現的,而且是調研階段,故先創建一個新的virtualenv環境,然後用pip安裝好supervisor包。
至此,基本的調研環境搭建完畢。當然,php-fpm和PHP環境以及前端的Nginx是早就ready的。
2. 分析php-fpm.sh腳本
通常編譯安裝PHP後,php-fpm這個2進制的C程序也會被編譯並安裝好,典型路徑在php_install_path/sbin/目錄下。該
目錄下還有個名為php-fpm.sh的腳本用於控制php-fpm進程的start/stop/restart/reload等動作。
./sbin/php-fpm.sh腳本中,」start」操作啟動了php-fpm主進程,其餘的操作都是通過向php-fpm master進程發signal實現的。
<code class="hljs bash">## code segment in php-fpm.sh
case "$1" in
start)
echo -n "Starting php-fpm "
## 下面這行是關鍵命令
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
wait_for_pid created $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed"
exit 1
else
echo " done"
fi
;;</code>
從上面是終端輸入」./sbin/php-fpm.sh
start」時,實際執行的代碼,可以看到,php-fpm進程的啟動參數是–daemonize
$php_opts,而$php_opts的值為」–fpm-config $php_fpm_CONF –pid $php_fpm_PID」。
注意: php-fpm.sh啟動php-fpm master進程時,傳入了daemonize參數,表明php-fpm master process以守護(daemon)方式啟動,而根據supervisor文檔的說明,當用supervisor監護進程時,被監護進程不能是守護進程,這是由於守護進程通常會在fork完子進程後就讓父進程」結束生命」,也即由supervisor創建的父進程退出,此時,supervisor無法再監護已退出進程創建出來的子進程。關於daemon process的行為,可以參考Linux Daemon Writing HOWTO一文來理解。
根據上面的分析,我們知道,只要supervisor啟動php-fpm進程時,不傳入daemonize參數即可。
3. 實現php-fpm主進程守護功能的supervisor配置文件
上面的分析已經告訴我們應該怎麼解決問題了,下面直接上驗證可用的配置文件。文件位於php-fpm.conf同級目錄下(典型路徑為php_install_path/etc/)。
<code class="hljs bash"><code class="hljs vhdl">
[inet_http_server] ; inet (TCP) server disabled by default
port=127.0.0.1:9015 ; (ip_address:port specifier, *:port for all iface)
[supervisord]
logfile=./var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=2 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=./var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)
identifier=sup.php-fpm ; (supervisord identifier, default is 'supervisor')
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=http://127.0.0.1:9015 ; use an http:// url to specify an inet socket
[program:php-fpm]
command=bash -c "sleep 1 && /home/slvher/tools/php/5.6.11/sbin/php-fpm --fpm-config /home/slvher/tools/php/5.6.11/etc/php-fpm.conf --pid /home/slvher/tools/php/5.6.11/var/run/php-fpm.pid" ; the program (relative uses PATH, can take args)
process_name=%(program_name)s ; process_name expr (default %(program_name)s)
autostart=true ; start at supervisord start (default: true)
autorestart=true ; whether/when to restart (default: unexpected)
startretries=5 ; max # of serial start failures (default 3)
exitcodes=0,2,70 ; 'expected' exit codes for process (default 0,2)
stopsignal=QUIT ; signal used to kill process (default TERM)
stopwaitsecs=2 ; max num secs to wait b4 SIGKILL (default 10)
</code></code>
配置文件結構通過查看supervisor文檔很容易就能掌握,有兩個配置項需要特別注意:
1) command
它指定了supervisor要監控的進程的啟動命令,可以看到,這里我們沒有給php-fpm傳入daemonize參數,其餘參數只是展開了php-fpm.sh中的shell變數而已。
大家已經注意到,command也不是直接調起php-fpm,而是通過bash -c執行了兩個命令,而第一個命令是sleep 1。這是由於php-fpm在stop後,其佔用的埠通常不能立即釋放,此時,supervisor以極快的速度試圖重新拉起進程時,可能會由於報如下錯誤而導致幾次retry均失敗:
<code class="hljs bash"><code class="hljs vhdl"><code class="hljs vbscript">## var/log/php-fpm.error.log
[18-Jul-2015 21:35:28] ERROR: unable to bind listening socket for address '127.0.0.1:9002': Address already in use (98)
[18-Jul-2015 21:35:28] ERROR: FPM initialization failed</code></code></code>
而supervisor目前還不支持delay restart功能,因此,這里只能通過先sleep再啟動的略顯tricky的方法來解決問題,結果表明,療效不錯且無副作用。-_-
2) autorestart
其文檔描述如下:
<code class="hljs bash"><code class="hljs vhdl"><code class="hljs vbscript"><code class="hljs livecodeserver">May be one of false, unexpected, or true. If false, the process will never be autorestarted. If unexpected, the process will be restart when the program exits with an exit code that is not one of the exit codes associated with this process』 configuration (see exitcodes). If true, the process will be unconditionally restarted when it exits, without regard to its exit code.</code></code></code></code>
其默認值是unexpected,表示若被監護進程的exit code異常時,supervisor才會重新拉起進程。這里設置為true,表明任何時候進程退出均會被再次拉起。
這樣配置好後,在本文第1步搭建好的virtualenv環境中,運行如下命令即可完成supervisor對php-fpm master進程的監護:
<code class="hljs bash"><code class="hljs vhdl"><code class="hljs vbscript"><code class="hljs livecodeserver"><code class="hljs avrasm">shell> supervisord -c etc/sup.php-fpm.conf</code></code></code></code></code>
然後,通過ps x | fgrep fpm可以看到,php-fpm主進程已經被拉起了。
然後,kill掉php-fpm主進程,再次ps x | fgrep fpm可以看到,一個新的php-fpm主進程會被supervisor創建出來。
至此,用supervisor守護php-fpm主進程以實現php-fpm的自動重啟的需求已經解決了。
㈢ PHP FPM源代碼反芻品味之四:事件處理
FPM master 進程啟動後,會進入函數fpm_event_loop,無限循環.
處理事件.
master 進程所做的的事,總的來說就是兩類:
簡稱timer事件,需按時運行,主要有3個:
簡稱fd事件,需從文件句柄(file descriptor)讀取到指令後,依指令運行.
重復一下,unix 下一切IO, 皆文件,socket ,socketpair,pipe 都返迴文件句柄(fd) 用於通信.
主要的fd有:
對於timer事件,多個事件在事件軸上是依次排列的,只需反復檢查,到時運行.
對於fd事件,需監聽多個fd,需用到我們第二篇講的IO多路復用技術.
如果滿足事件條件,則處理事件內容.
FPM設計上,兩類事件使用同一個結構,並且事件觸發條件和事件處理邏輯放到同一個事件對象里(C語言對象就是結構體).
舉個例子, 打鈴下課,打鈴是觸發條件,下課是事件內容,兩個同時放到一個事件對象 ,這是一個很好的設計.
fd值: -1
flags值:FPM_EV_PERSIST
which值: FPM_EV_TIMEOUT
fd值: 獲取觸發指令的文件fd
flags值: FPM_EV_EDGE(fd事件底層的邊緣觸發標志,需系統支持)
which值: FPM_EV_READ
兩類事件分別放在兩個事件隊列
static struct fpm_event_queue_s *fpm_event_queue_timer = NULL;
static struct fpm_event_queue_s *fpm_event_queue_fd = NULL;
事件隊列的結構很常見,雙向隊列:
typedef struct fpm_event_queue_s {
struct fpm_event_queue_s *prev;
struct fpm_event_queue_s *next;
struct fpm_event_s *ev;
} fpm_event_queue;
4移除事件 (fpm_event_del -> fpm_event_queue_del)
簡單的出列操作:
static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev)
對於fd事件,需在底層事件輪詢機制里移除(如:epoll)
5,運行事件回調函數:
6, 底層事件輪詢模塊結構
不同的操作系統,支持不同的IO事件機制,linux 支持epoll,
windows支持select, freebsd 支持kqueue,這個結構統一操作介面
在函數fpm_event_init_main里 調用mole->init初始化
fpm 里對應的配置
master進程在fpm_event_loop函數里無限循環,處理定時任務和fd事件.
期間會在mole->wait阻塞片刻,對於epoll機制,就是epoll_wait.
㈣ php如何把自身進程設置為系統進程
進程管理-防止進程成為僵屍進程
創建好了進程,那麼怎麼對子進程進行管理呢?
使用信號,對子進程的管理,一般有兩種情況:(推薦學習:PHP編程從入門到精通)
posix_kill():此函數並不能顧名思義,它通過向子進程發送一個信號來操作子進程,在需要要時可以選擇給子進程發送進程終止信號來終止子進程;
pcntl_waitpid():等待或返回fork的子進程狀態,如果指定的子進程在此函數調用時已經退出(俗稱僵屍進程),此函數將立刻返回,並釋放子進程的所有系統資源,此進程可以避免子進程變成僵屍進程,造成系統資源浪費;
孤兒進程:父進程掛了,子進程被pid=1的init進程接管(wait/waitpid),直到子進程自身生命周期結束被系統回收資源和父進程 採取相關的回收操作
僵屍進程:子進程exit退出,父進程沒有通過wait/waitpid獲取子進程狀態,子進程佔用的進程號等描述資源符還存在,產生危害:例如進程號是有限的,無法釋放進程號導致未來可能無進程號可用
**父進程中使用:pcntl_wait或者pcntl_waitpid的目的就是防止worker成為僵屍進程
作用:使用pcntl_wait()後,在子進程死掉後,父進程也會被停止**
最後我們通過下圖來簡單的總結和描述這個多進程實現的過程:
.png
進程管理-進程間通信
隊列:如Redis,推薦
socket:推薦
管道:實現復雜,且管道(pipe),使用文件形式存在,存在硬碟IO性能瓶頸
信號:承載信息量少,不好管理
進程管理-切換為守護進程
使用&實現
php deadloop.php &
相關資源:Nginx使用的php-fpm的兩種進程管理方式及優化-其它代碼類資源...
打開CSDN APP,看更多技術內容
php 進程管理,PHP 進程管理器 PHP-FPM_阿喵看海外的博客
php-fpm是PHP的一個進程管理器。php下面的眾多work進程皆有php-fpm進程管理器管理。 php-fpm的工作原理 php-fpm全名是PHP FastCGI進程管理器。php-fpm啟動後會先讀php.ini,然後再讀相應的conf配置文件,conf配置可以覆蓋php.ini的配置。
繼續訪問
php-fpm解讀-進程管理的三種模式_april2nd的博客_php-fpm...
php-fpm進程管理一共有三種模式:ondemand、static、dynamic,我們可以在同一個fpm的master配置三種模式,看下圖1。php-fpm的工作模式和nginx類似,都是一個master,多個worker模型。每個worker都在accept本pool內的監聽套接字(linux已不存在驚...
繼續訪問
淺談PHP進程管理
這篇文章是對之前一篇文章的補充和改進, 創建一個主(master)進程,主進程安裝定時器,每隔5分鍾檢測一次隊列長度,根據隊列長度計算需要的worker進程, 然後創建或者殺掉子進程。這樣做的好處是防止隊列堆積,任務得不到及時處理。更新業務代碼,只需要reload操作即可。 整個流程有以下知識點: 創建守護進程的步驟: 設置默認文件許可權 fork一個進程,父進程退出 調用setsid創建一個新的會話 將當前工作目錄更改為根目錄 關閉不再需要的文件描述符 使用信號實現定時器 上一篇定時器依賴於系統的定時任務,這次使用鬧鍾信號實現,php 5.3.0以下的版本依賴於ticks,
php 腳本 fpm緩存,PHP生命周期及fpm(FastCGI進程管理器)的運作方式
PHP在web方式中如何改了文件就立即生效的,重要的幾個概念:sapi: 可以簡單的理解為php引擎對外的一個統一介面,使得php可以和外部程序進行交互php的生命周期中關鍵四個調用: MINT -> RINT -> RSHUTDOWN -> MSHUTDOWNfpm: fastcgi進程管理器fpm方式的流程就是:fpm通過sapi介面與php進程交互1.fpm啟動會調用各擴展...
繼續訪問
Linux下搭建PHP開發環境,Php-Fpm進程管理。_黑夜開發者的博客
目前PHP項目開發幾種比較流行的架構搭建中,LNMP在性能方面是最好的,正因為如此,使得LNMP架構逐漸流行起來,今天,前面提到了Nginx部署,由於項目實際環境的需要,今天就在說一下怎麼部署PHP。 環境 ...
繼續訪問
php而為,為高負載而生的 PHP 進程管理器 —— PHP-PM (PPM)
PHP-PM 可以用於php應用程序的進程管理,增壓和負載均衡.它使用 ReactPHP 實現php的事件驅動和非阻塞I/O。 它是基於 ReactPHP,最好是工作在基於請求-響應式的框架,像Symfony的HTTPKernel。這樣做是為了減少php啟動(包括變數聲明,載入和...
繼續訪問
最新發布 php進程管理
php 進程管理 tasks 過多
繼續訪問
PHP進程實現&管理
運行環境為Linux,模式為CLI DEMO /*要創建的子進程*/ $manager = [ 'work1', 'work2', 'work3', ]; /*當前進程名稱*/ $status = file_exists('/proc/' . getmypid() . '/status'); $bash = '-'; if ($status) { $bash = file('/proc/' . getmypid() . '/status', FILE_IGNORE.
繼續訪問
php的管理進程管理利器--php-fpm_weixin_33778778的博客
mod_php 模式是將php模塊安裝到apache中,所以每一次apache結束的請求呢,都會產生一條進程,這個進程就完整的包括php的各種運算計算等操作。 從圖中我們很清晰的可以看到,apache每接收一個請求,都會產生一個進程來連接php通過sapi來完成請求...
繼續訪問
php-frm進程管理,PHP內核探索-進程管理
進程管理方式首先我們了解一下php的三種不同的進程管理方式:static:靜態管理進程。在啟動時,master按照pm.max_children配置fork出對應數量的work進程,即work的進程是固定不變的。dynamic:動態管理進程。在fpm啟動時先按照pm.start_servers初始化一定數量的work進程,運行期間如果master發現空閑work進程低於pm.min_spare_s...
繼續訪問
理解php-fpm的兩種執行方式
前段時間配置php-fpm的時候,無意間發現原來他還有兩種執行方式。與Apache一樣,他的進程數也是可以根據設置分為動態和靜態的。關於Apache的工作方式及對應的設置方法,我已經在《Ubuntu下配置Apache的Worker模式》一文中寫出,這里不再多說。 而php-fpm也是同樣存在兩種方式,一種是直接開啟指定數量的php-fpm進程,不再增加或者減少;另一...
繼續訪問
php進程原理_PHP進程管理器php-fpm的工作原理
PHP進程管理器php-fpm的工作原理發布時間:2020-07-21 17:46:39來源:億速雲閱讀:133作者:小新今天小編給大家分享的是PHP進程管理器php-fpm的工作原理,相信很多人都不太了解,為了讓大家更加了解,所以給大家總結了以下內容,一起往下看吧。一定會有所收獲的哦。php-fpm是什麼php-fpm是PHP的一個進程管理器。php下面的眾多work進程皆有php-fpm進程管...
繼續訪問
如何管理php常駐進程,一看就懂系列之 如何實現與控制php常駐進程-Go語言中文社區...
前言關於如何實現與控制php常駐進程,不管是google還是上進行搜索,都沒有感覺看起來賞心悅目的解答,於是決定自己動手總結下。有同學會問了,整這個干甚?簡單的說就是,可以讓一個php腳本一直處於運行的狀態。從而實現將項目中某些耗時操作非同步化,進隊列後由php腳本取出再執行。有同學又會問了,直接在伺服器直接命令「php test.php &」,不就可以實現了?那麼這樣做的話有三點...
繼續訪問
PHP-FPM(PHP進程管理器)
PHP-FPM
繼續訪問
php 進程管理,從 0 到 1 優雅的實現 PHP 多進程管理
_| |_ __ __ _ _ __ _ _| |_ ___| '_ \ / _` | '__| | | | __/ _ \| | | | (_| | | | |_| | || (_) ||_| |_|\__,_|_| \__,_|\__\___/ .TIGERB.cnAn object-oriented multi process manager for PHPVersion: 0...
繼續訪問
php-fpm進程管理的三種模式
轉載自 php-fpm解讀-進程管理的三種模式 —程序媛大麗 標明轉載以示尊重 感謝原作者的分享。 php-fpm進程管理一共有三種模式:ondemand、static、dynamic,我們可以在同一個fpm的master配置三種模式,看下圖1。php-fpm的工作模式和nginx類似,都是一個master,多個worker模型。每個worker都在accept本pool內的監聽套接字(linu...
繼續訪問
php 進程管理那點事
之前本地開發和環境一直用的集成環境,最近新項目 集成了php7+nginx 跑了一段時間發現偶爾 有php進程退出的情況 排查原因 nginx log: 1111 upstream timed out (10060: A connection attempt failed because the connected party did not properly respond after ...
繼續訪問
從0到1優雅的實現PHP多進程管理
_ | | _ __ __ _ _ __ _ _| |_ ___ | '_ \ / _` | '__| | | | __/ _ \ | | | | (_| | | | |_| | || (_) | |_| |_|\__,_|_| \__,_|\__\___/ ...
繼續訪問
熱門推薦 php-fpm安裝、配置與優化
轉載自:https://www.zybuluo.com/phper/note/89081 1、php中fastcgi和php-fpm是什麼東西 最近在研究和學習php的性能方面的知識,看到了factcgi以及php-fpm,發現我對他們是少之又少的理解,可以說幾乎是一無所知,想想還是蠻可怕的。決定仔細的學習一下關於這方面的知識。 參考和學習了以下文章: 1. mod_php和
繼續訪問
php-fpm的兩種進程管理模式
php-fpm的兩種進程管理模式 php-fpm的進程數也是可以根據設置分為動態和靜態的。 一種是直接開啟指定數量的php-fpm進程,不再增加或者減少; 另一種則是開始的時候開啟一定數量的php-fpm進程,當請求量變大的時候,動態的增加php-fpm進程數到上限,當空閑的時候自動釋放空閑的進程數到一個下限。 這兩種不同的執行方式,可以根據伺服器的實際需求來進行調整。 這里先說一下涉及
繼續訪問
7、Php-Fpm進程管理
1、進程管理 php-fpm採用的是master-worker的進程方式。其中, master負責監聽埠,等待鏈接;其次,注冊信號,可以通過信息好master進行管理 worker負責處理具體的邏輯 如下圖所示 2、信號管理 master進程可以理解如下信號 信號 含義 INT, TERM 立刻終止 ...
繼續訪問
php進程式控制制
簡介 PHP的進程式控制制支持實現了Unix方式的進程創建, 程序執行, 信號處理以及進程的中斷。 進程式控制制不能被應用在Web伺服器環境,當其被用於Web服務環境時可能會帶來意外的結果。 這份文檔用於闡述每個進程式控制制函數的通常用法。關於Unix進程式控制制的更多信息建議您查閱 系統文檔中關於fork(2),waitpid(2),signal(2)等的部分或更全面的參考資料比如 《Unix環境高級編程》
繼續訪問
php進程管理
php 進程管理
㈤ php性能加速之opcache
OPcache 是一個通過將 PHP 腳本預編譯的位元組碼存儲到共享內存中來提升 PHP 的性能的PHP擴展。 存儲預編譯位元組碼的好處就是 省去了每次載入和解析 PHP 腳本的開銷。PHP 5.5.0 及後續版本中已經綁定了 OPcache 擴展。
首先,我們來先大致了解下http-->nginx-->php-fpm-->php處理的流程機制
http request ---> nginx(代理)----> php-fpm(master 進程,分配)----> php-fpm(worker處理 ) ---->php-cgi(1.啟動ZEND引擎,載入配置,載入mole,2.初始化php腳本進行詞法分析,語法分析,生成語法樹,3.ZEND引擎編譯語法樹,生成可執行位元組碼。4.執行位元組碼,返回處理結果)
opcache 就緩存了php腳本預編譯的位元組碼避免每次處理請求都重復執行(php-cgi處理的1,2,3)步驟,這樣可以使得php性能大大提高。
php.ini
1.重啟php-fpm
2.列印phpinfo(),看到有ZEND OPcache就證明已經開啟成功了
㈥ nginx與php-fpm的簡單的關系流程圖
流程:
1,首先Browser通過Http協議發送一個請求到Nginx伺服器
2,Nginx服務判斷是否為靜態資源是的話直接放回,否則載入nginx.conf配置文件里的fastcgi模塊。
3,Nginx通過fastcgi_pass (默認是127.0.0.0:9000)把對應的請求按照fastcgi協議轉發到PHP-FPM,php-fpm的master進程會監聽9000埠,然後給php-fpm work進程,work進程 再調用php-cgi解析器並且生成php執行環境再去執行解析對應的PHP文件
4,解析完成再返回給nginx,然後返回給瀏覽器。
註:
1,php-fpm會生成一個master進程用於監控9000埠,負責分發給下面的work進程
2,fastcgi 是一種協議用於解析器和伺服器之間的交互
㈦ PHP進程管理三種模式
ondemand:按請示創建進程數;
dynamic:初始化啟動number進程數;
static:固定啟動進程數;
php-fpm進程管理一共有三種模式: ondemand、static、dynamic ,我們可以在同一個fpm的master配置三種模式,看下圖1。php-fpm的工作模式和nginx類似,都是一個master,多個worker模型。每個worker都在accept本pool內的監聽套接字(linux已不存在驚群現象)。
ondemand
在php-fpm啟動的時候,不會給這個pool啟動任何一個worker,是按需啟動,當有連接過來才會啟動。
配置文件(我的配置文件地址為:/usr/local/php/etc/php-fpm.conf)
當前pool的名字為test
原理
ondemand原理圖
1. 從上圖可以看出,新建worker的觸發條件是連接的到來,而不是實際的請求(例如,只進行連接比如telnet,不發請求數據也會新建worker)
2. worker的數量受限於pm.max_children配置,同時受限全局配置process.max(准確的說,三種模式都受限於全局配置)
3.1秒定時器作用
找到空閑worker,如果空閑時間超過pm.process_idle_timeout大小,關閉。這個機制可能會關閉所有的worker。
配置項要求
1. pm.max_children> 0
2. pm.process_idle_timeout> 0,如果不設置,默認10s
優缺點
優點:按流量需求創建,不浪費系統資源(在硬體如此便宜的時代,這個優點略顯雞肋)
缺點:由於php-fpm是短連接的,所以每次請求都會先建立連接,建立連接的過程必然會觸發上圖的執行步驟,所以,在大流量的系統上master進程會變得繁忙,佔用系統cpu資源,不適合大流量環境的部署
dynamic
在php-fpm啟動時,會初始啟動一些worker,在運行過程中動態調整worker數量,worker的數量受限於pm.max_children配置,同時受限全局配置process.max
當前pool的名字為test
原理
dynamic原理圖
1. 1秒定時器作用
檢查空閑worker數量,按照一定策略動態調整worker數量,增加或減少。增加時,worker最大數量<=max_children· <=全局process.max;減少時,只有idle >pm.max_spare_servers時才會關閉一個空閑worker。
idle > pm.max_spare_servers,關閉啟動時間最長的一個worker,結束本次處理
idle >= pm.max_children,列印WARNING日誌,結束本次處理
idle < pm.max_children,計算一個num值,然後啟動num個worker,結束本次處理
配置項要求
1. pm.min_spare_servers/pm.max_spare_servers有效范圍(0,pm.max_children]
2. pm.max_children> 0
3. pm.min_spare_servers<=pm.max_spare_servers
4. pm.start_servers有效范圍[pm.min_spare_servers,pm.max_spare_servers]如果沒有配置,默認pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2
優缺點
優點:動態擴容,不浪費系統資源,master進程設置的1秒定時器對系統的影響忽略不計;
缺點:如果所有worker都在工作,新的請求到來只能等待master在1秒定時器內再新建一個worker,這時可能最長等待1s;
static
php-fpm啟動採用固定大小數量的worker, 在運行期間也不會擴容,雖然也有1秒的定時器,僅限於統計一些狀態信息,例如空閑worker個數,活動worker個數,網路連接隊列長度等信息。
當前pool的名字為test
原理
配置項要求
1、pm.max_children> 0 必須配置,且只有這一個參數生效
優缺點
如果配置成static,只需要考慮max_children的數量,數量取決於cpu的個數和應用的響應時間,我司配置的是50。
我司不考慮動態的增加減少那麼十幾個或者幾十個worker,我們的內存沒有緊張到這個程度,所以,我們一步到位,把worker數配置到支持最大流量,(哈哈,50也是隨便定的,足矣足矣呢)
最後我們再介紹下worker的工作流程
fastcgi與php-fpm的關系一句話解讀:fastcgi只是通信應用協議,php-fpm就是實現了fastcig協議,並嵌入了一個 PHP 解釋器。
㈧ cgi、fastcgi、php-cgi、php-fpm異同
1. cgi
- 通用網關介面,就是外部應用程序(cgi程序)與web伺服器之間的介面標准。
- nginx是內容分發者,如果是請求index.php,根據配置文件內容得知不是靜態文件,就會去找對應的cgi程序進行解析
- cgi就是規定要傳那些數據,以什麼格式傳遞給後方進行處理的協議
- cgi工作模式,一個請求發送過來,啟動cgi解釋器(創建進程)-> 邏輯處理 -> 退出 (fork and exec 模式) 每次都需要重新創建進程,載入配置,浪費系統資源
2. fastcgi
- 快速通用網關介面,常駐型的cgi,不用每次都fork進程,其會使cgi解解釋器進程常駐內存,所以性能較高
- master-worker模型,伺服器啟動時載入fastcgi進程管理器
- fastcgi會進行自身初始化,初始化時會創建多個進程
- 請求到達web伺服器後,fastcgi進程管理器會選擇並通過socket連接到一個cgi解釋器
3. php-cgi
- php自帶的cgi管理器
- php-cgi的缺點,不能平滑重啟,需要重啟php-cgi才能使php.ini生效
4. php-fpm
- php-fpm是php的一種fastcgi的實現,管理php的fastcgi進程池
- 能夠調度php-cgi程序
- 能夠實現平滑重啟
- php-fpm創建一個master進程,然後創建進程池,監聽socket,fork出多個子進程,子進程各自accept請求,php-fpm的子進程同時只能響應一個請求,處理完一個請求才可以accept下一個請求,多進程,同步阻塞模型
- master和worker進程之間不直接進行通信,master通過共享內存獲取worker進程信息,master進程發送信號通知worker進程
- php-fpm可以同時監聽多個埠,每個埠對應一個worker pool
- worker是cgi程序,php-fpm是fastcgi協議的php是實現
㈨ php-fpm的工作機制
概括來說,fpm 的實現就是創建一個 master 進程,在 master 進程中創建並監聽 socket,然後 fork 出多個子進程,這些子進程各自 accept 請求,子進程的處理非常簡單,它在啟動後阻塞在 accept 上,有請求到達後開始讀取請求數據,讀取完成後開始處理然後再返回,在這期間是不會接收其它請求的,也就是說 fpm 的子進程同時只能響應一個請求,只有把這個請求處理完成後才會 accept 下一個請求,這一點與 nginx 的事件驅動有很大的區別,nginx 的子進程通過 epoll 管理套接字,如果一個請求數據還未發送完成則會處理下一個請求,即一個進程會同時連接多個請求,它是非阻塞的模型,只處理活躍的套接字。
fpm 的 master 進程與 worker 進程之間不會直接進行通信,master 通過共享內存獲取 worker 進程的信息,比如 worker 進程當前狀態、已處理請求數等,當 master 進程要殺掉一個 worker 進程時則通過發送信號的方式通知 worker 進程。
fpm 可以同時監聽多個埠,每個埠對應一個 worker pool,而每個 pool 下對應多個 worker 進程,類似 nginx 中 server 概念。
在 php-fpm.conf 中通過[pool name]聲明一個 worker pool:
啟動 fpm 後查看進程:
具體實現上 worker pool 通過fpm_worker_pool_s這個結構表示,多個 worker pool 組成一個單鏈表
接下來看下 fpm 的啟動流程,從main()函數開始:
fpm_init()主要有以下幾個關鍵操作:
(1) fpm_conf_init_main():
解析 php-fpm.conf 配置文件,分配 worker pool 內存結構並保存到全局變數中:fpm_worker_all_pools,各 worker pool 配置解析到fpm_worker_pool_s->config中。
(2)fpm_scoreboard_init_main():
分配用於記錄 worker 進程運行信息的共享內存,按照 worker pool 的最大 worker 進程數分配,每個 worker pool 分配一個fpm_scoreboard_s結構,pool 下對應的每個 worker 進程分配一個fpm_scoreboard_proc_s結構。
(3)fpm_signals_init_main():
這里會通過socketpair()創建一個管道,這個管道並不是用於 master 與 worker 進程通信的,它只在 master 進程中使用,具體用途在稍後介紹 event 事件處理時再作說明。另外設置 master 的信號處理 handler,當 master 收到 SIGTERM、SIGINT、SIGUSR1、SIGUSR2、SIGCHLD、SIGQUIT 這些信號時將調用sig_handler()處理:
(4)fpm_sockets_init_main()
創建每個 worker pool 的 socket 套接字。
(5)fpm_event_init_main():
啟動 master 的事件管理,fpm 實現了一個事件管理器用於管理 IO、定時事件,其中 IO 事件通過 kqueue、epoll、poll、select 等管理,定時事件就是定時器,一定時間後觸發某個事件。
在fpm_init()初始化完成後接下來就是最關鍵的fpm_run()操作了,此環節將 fork 子進程,啟動進程管理器,另外 master 進程將不會再返回,只有各 worker 進程會返回,也就是說fpm_run()之後的操作均是 worker 進程的。
在 fork 後 worker 進程返回了監聽的套接字繼續 main() 後面的處理,而 master 將永遠阻塞在fpm_event_loop(),接下來分別介紹 master、worker 進程的後續操作。
fpm_run()執行後將 fork 出 worker 進程,worker 進程返回main()中繼續向下執行,後面的流程就是 worker 進程不斷 accept 請求,然後執行 PHP 腳本並返回。整體流程如下:
worker 進程一次請求的處理被劃分為 5 個階段:
worker 處理到各個階段時將會把當前階段更新到fpm_scoreboard_proc_s->request_stage,master 進程正是通過這個標識判斷 worker 進程是否空閑的。
接下來我們來看下 master 是如何管理 worker 進程的,首先介紹下三種不同的進程管理方式:
前面介紹到在fpm_run()中 master 進程將進入fpm_event_loop():
這就是 master 整體的處理,其進程管理主要依賴注冊的幾個事件,接下來我們詳細分析下這幾個事件的功能。
(1)sp[1]管道可讀事件:
在 fpm_init() 階段 master 曾創建了一個全雙工的管道:sp,然後在這里創建了一個 sp[0] 可讀的事件,當 sp[0] 可讀時將交由 fpm_got_signal() 處理,向 sp[1] 寫數據時 sp[0] 才會可讀,那麼什麼時機會向 sp[1] 寫數據呢?前面已經提到了:當 master 收到注冊的那幾種信號時會寫入 sp[1] 端,這個時候將觸發 sp[0] 可讀事件。
這個事件是 master 用於處理信號的,我們根據 master 注冊的信號逐個看下不同用途:
具體處理邏輯在 fpm_got_signal() 函數中,這里不再羅列。
(2)fpm_pctl_perform_idle_server_maintenance_heartbeat():
這是進程管理實現的主要事件,master 啟動了一個定時器,每隔 1s 觸發一次,主要用於 dynamic、ondemand 模式下的 worker 管理,master 會定時檢查各 worker pool 的 worker 進程數,通過此定時器實現 worker 數量的控制,處理邏輯如下:
(3)fpm_pctl_heartbeat():
這個事件是用於限制 worker 處理單個請求最大耗時的,php-fpm.conf 中有一個request_terminate_timeout的配置項,如果 worker 處理一個請求的總時長超過了這個值那麼 master 將會向此 worker 進程發送kill -TERM信號殺掉 worker 進程,此配置單位為秒,默認值為 0 表示關閉此機制,另外 fpm 列印的 slow log 也是在這里完成的。
除了上面這幾個事件外還有一個沒有提到,那就是 ondemand 模式下 master 監聽的新請求到達的事件,因為 ondemand 模式下 fpm 啟動時是不會預創建 worker 的,有請求時才會生成子進程,所以請求到達時需要通知 master 進程,這個事件是在fpm_children_create_initial()時注冊的,事件處理函數為fpm_pctl_on_socket_accept(),具體邏輯這里不再展開,比較容易理解。
原文出處: https://www.fanhao.com/2017/10/internal-php-fpm.html