作為一個(gè)phper,一直會(huì)接觸到php搔驼、nignx等的相關(guān)配置谈火,相關(guān)的名詞比如PHP-FPM、CGI舌涨、Fast CGI糯耍、SAPI等等應(yīng)該都或多或少接觸過,但自己對(duì)于這些知識(shí)點(diǎn)的掌握其實(shí)相對(duì)比較分散且形成不了一定的關(guān)系囊嘉,于是在網(wǎng)上搜了相關(guān)的文章并結(jié)合自己的一些理解温技,整理成此文,便于記錄扭粱。
首先荒揣,先看一個(gè)最簡(jiǎn)單的服務(wù)器請(qǐng)求和響應(yīng)的流程
在這個(gè)例子中,Web Server(如Nginx)只是內(nèi)容的分發(fā)者焊刹,如果客戶端請(qǐng)求的是 index.html等靜態(tài)文件系任,那么Web Server會(huì)去文件系統(tǒng)中找到這個(gè)文件,發(fā)送給瀏覽器虐块,這里分發(fā)的是靜態(tài)數(shù)據(jù)俩滥。
如果請(qǐng)求的是php文件,nginx無法直接處理贺奠,就會(huì)去配置文件nginx中尋找是否有對(duì)于php文件的配置
server
{
listen 80 default_server;
server_name _;
index index.html index.htm index.php;
root /home/wwwroot/test/public;
#error_page 404 /404.html;
location ~ [^/]\.php(/|$)
{
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
...
在nginx.conf文件中霜旧,大家可以發(fā)現(xiàn)有這么一段配置,如果是php文件的請(qǐng)求儡率,就會(huì)分發(fā)到這個(gè)邏輯中挂据。
這里定義的是與php解析器進(jìn)行通訊的一些配置參數(shù)以清,其中fastcgi_pass參數(shù)約定了nginx和php進(jìn)行通訊的socket是unix:/tmp/php-cgi.sock,后文會(huì)講到php同時(shí)也會(huì)對(duì)應(yīng)的監(jiān)聽這個(gè)端口
PS:部分配置文件中這個(gè)地址會(huì)是一個(gè)IP+端口號(hào)的TCP形式崎逃,TCP可以跨服務(wù)器掷倔,而UNIX Domain Socket不經(jīng)過網(wǎng)絡(luò)層,只能用于Nginx跟PHP-FPM都在同一服務(wù)器的場(chǎng)景
這樣子友誼的小橋就這樣順利的搭建起來了。現(xiàn)在小橋搭建好了个绍,剩下的就是通訊的數(shù)據(jù)格式的統(tǒng)一了勒葱,這時(shí)候需要用到Fast-cgi協(xié)議,這個(gè)協(xié)議約定了這兩者通訊的數(shù)據(jù)格式
CGI:是 Web Server 與 Web Application 之間數(shù)據(jù)交換的一種協(xié)議,因?yàn)槠涿看握?qǐng)求都要執(zhí)行fork-and-execut的流程巴柿,所以存在較大的性能瓶頸凛虽,現(xiàn)在已經(jīng)很少使用
FastCGI:同 CGI,是一種通信協(xié)議广恢,但比 CGI 在效率上做了一些優(yōu)化凯旋,采用了常駐(long-live)型來減少系統(tǒng)的開銷,使得性能大大提升
前面說過Fast CGI只是一種協(xié)議(看到有不少文章會(huì)將這是一個(gè)應(yīng)用程序钉迷,其實(shí)是不對(duì)的)瓦阐,那遵循這個(gè)協(xié)議的實(shí)現(xiàn)者就是我們熟悉的PHP-FPM(FastCGI Process Manager),它的架構(gòu)是由一個(gè)manager進(jìn)程負(fù)責(zé)管理一個(gè)進(jìn)程池篷牌,進(jìn)程池中就是子進(jìn)程php-cgi
打開php安裝目錄下的php-fpm.conf,可以看到有以下一段參數(shù)配置
listen = /tmp/php-cgi.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = www
可以看到php-fpm下同樣監(jiān)聽了/tmp/php-cgi.sock這個(gè)socket踏幻,這和前面nginx.conf的配置是對(duì)應(yīng)的
于是請(qǐng)求最后就交由到FastCGI子進(jìn)程來進(jìn)行處理枷颊,F(xiàn)astCGI子進(jìn)程完成處理后,將標(biāo)準(zhǔn)輸出和錯(cuò)誤信息從同一連接返回Web Server進(jìn)行輸出
所以一個(gè)php請(qǐng)求的自上而下的流程如下圖:
這里有一個(gè)名詞放在文末將可能會(huì)更加的便于理解该面,大家可以看到我在圖中將CGI包含在一個(gè)叫SAPI的類型下夭苗,那什么是SAPI呢?下面的解釋引用至鳥哥的博客
SAPI: Server abstraction API隔缀,研究過PHP架構(gòu)的同學(xué)應(yīng)該知道這個(gè)東東的重要性题造,它提供了一個(gè)接口,使得PHP可以和其他應(yīng)用進(jìn)行交互數(shù)據(jù)
前面我們講過的Fast CGI猾瘸,還有其他比如shell的CLI界赔,以及apache的mod_php5,都屬于SAPI的范疇牵触,目的是為了讓各個(gè)服務(wù)器抽象層之間遵守著相同的約定淮悼,使php本身和上層應(yīng)用解耦隔離,使php的可移植性更強(qiáng)揽思。