著作權(quán)歸作者所有。
商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)糠溜,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處淳玩。
作者:仁風(fēng)H
鏈接:http://zhuanlan.zhihu.com/p/20694204
來源:知乎
網(wǎng)絡(luò)上有很多關(guān)于如何配置 Nginx + FPM 的文章,但它們更多從操作的角度出發(fā)非竿,告訴我們?cè)趺醋鐾勺牛珔s沒有告訴我們?yōu)槭裁匆@么做,本文從 Nginx 與 FPM 的工作機(jī)制出發(fā),探討配置背后的原理承匣,讓我們真正理解 Nginx 與 PHP 是如何協(xié)同工作的蓖乘。
要說 Nginx 與 PHP 是如何協(xié)同工作的,首先得說 CGI (Common Gateway Interface) 和 FastCGI 這兩個(gè)協(xié)議韧骗。
CGI 是 Web Server 與后臺(tái)語言交互的協(xié)議嘉抒,有了這個(gè)協(xié)議,開發(fā)者可以使用任何語言處理 Web Server 發(fā)來的請(qǐng)求袍暴,動(dòng)態(tài)的生成內(nèi)容些侍。但 CGI 有一個(gè)致命的缺點(diǎn),那就是每處理一個(gè)請(qǐng)求都需要 fork 一個(gè)全新的進(jìn)程政模,隨著 Web 的興起岗宣,高并發(fā)越來越成為常態(tài),這樣低效的方式明顯不能滿足需求淋样。就這樣耗式,F(xiàn)astCGI 誕生了,CGI 很快就退出了歷史的舞臺(tái)趁猴。FastCGI刊咳,顧名思義為更快的 CGI,它允許在一個(gè)進(jìn)程內(nèi)處理多個(gè)請(qǐng)求躲叼,而不是一個(gè)請(qǐng)求處理完畢就直接結(jié)束進(jìn)程,性能上有了很大的提高企巢。
至于 FPM (FastCGI Process Manager)枫慷,它是 FastCGI 的實(shí)現(xiàn),任何實(shí)現(xiàn)了 FastCGI 協(xié)議的 Web Server 都能夠與之通信浪规。FPM 之于標(biāo)準(zhǔn)的 FastCGI或听,也提供了一些增強(qiáng)功能,具體可以參考官方文檔:PHP: FPM Installation笋婿。
FPM 是一個(gè) PHP 進(jìn)程管理器誉裆,包含 master 進(jìn)程和 worker 進(jìn)程兩種進(jìn)程:master 進(jìn)程只有一個(gè),負(fù)責(zé)監(jiān)聽端口缸濒,接收來自 Web Server 的請(qǐng)求足丢,而 worker 進(jìn)程則一般有多個(gè) (具體數(shù)量根據(jù)實(shí)際需要配置),每個(gè)進(jìn)程內(nèi)部都嵌入了一個(gè) PHP 解釋器庇配,是 PHP 代碼真正執(zhí)行的地方斩跌,下圖是我本機(jī)上 fpm 的進(jìn)程情況,1一個(gè) master 進(jìn)程捞慌,3個(gè) worker 進(jìn)程:
從 FPM 接收到請(qǐng)求耀鸦,到處理完畢,其具體的流程如下:
FPM 的 master 進(jìn)程接收到請(qǐng)求
master 進(jìn)程根據(jù)配置指派特定的 worker 進(jìn)程進(jìn)行請(qǐng)求處理啸澡,如果沒有可用進(jìn)程袖订,返回錯(cuò)誤氮帐,這也是我們配合 Nginx 遇到502錯(cuò)誤比較多的原因。
worker 進(jìn)程處理請(qǐng)求洛姑,如果超時(shí)上沐,返回504錯(cuò)誤
請(qǐng)求處理結(jié)束,返回結(jié)果
FPM 從接收到處理請(qǐng)求的流程就是這樣了吏口,那么 Nginx 又是如何發(fā)送請(qǐng)求給 fpm 的呢奄容?這就需要從 Nginx 層面來說明了。
我們知道产徊,Nginx 不僅僅是一個(gè) Web 服務(wù)器昂勒,也是一個(gè)功能強(qiáng)大的 Proxy 服務(wù)器,除了進(jìn)行 http 請(qǐng)求的代理舟铜,也可以進(jìn)行許多其他協(xié)議請(qǐng)求的代理戈盈,包括本文與 fpm 相關(guān)的 fastcgi 協(xié)議。為了能夠使 Nginx 理解 fastcgi 協(xié)議谆刨,Nginx 提供了 fastcgi 模塊來將 http 請(qǐng)求映射為對(duì)應(yīng)的 fastcgi 請(qǐng)求塘娶。
Nginx 的 fastcgi 模塊提供了 fastcgi_param 指令來主要處理這些映射關(guān)系,下面 Ubuntu 下 Nginx 的一個(gè)配置文件痊夭,其主要完成的工作是將 Nginx 中的變量翻譯成 PHP 中能夠理解的變量刁岸。
除此之外,非常重要的就是 fastcgi_pass 指令了她我,這個(gè)指令用于指定 fpm 進(jìn)程監(jiān)聽的地址虹曙,Nginx 會(huì)把所有的 php 請(qǐng)求翻譯成 fastcgi 請(qǐng)求之后再發(fā)送到這個(gè)地址。下面一個(gè)簡單的可以工作的 Nginx 配置文件:
在這個(gè)配置文件中番舆,我們新建了一個(gè)虛擬主機(jī)酝碳,監(jiān)聽在 80 端口,Web 根目錄為 /home/rf/projects/wordpress恨狈。然后我們通過 location 指令疏哗,將所有的以 .php 結(jié)尾的請(qǐng)求都交給 fastcgi 模塊處理,從而把所有的 php 請(qǐng)求都交給了 fpm 處理禾怠,從而完成 Nginx 到 fpm 的閉環(huán)返奉。
如此以來女器,Nginx 與 FPM 通信的整個(gè)流程應(yīng)該比較清晰了吧侍咱。
以上
2016年4月2日
北京