在搭建 LAMP/LNMP 服務(wù)器時嘶伟,會經(jīng)常遇到?PHP-FPM怎憋、FastCGI和CGI 這幾個概念。如果對它們一知半解九昧,很難搭建出高性能的服務(wù)器绊袋。接下來我們就以圖形方式,解釋這些概念之間的關(guān)系铸鹰。
基礎(chǔ)
在整個網(wǎng)站架構(gòu)中癌别,Web Server(如Apache)只是內(nèi)容的分發(fā)者。舉個栗子蹋笼,如果客戶端請求的是 index.html展姐,那么Web Server會去文件系統(tǒng)中找到這個文件,發(fā)送給瀏覽器剖毯,這里分發(fā)的是靜態(tài)數(shù)據(jù)圾笨。
如果請求的是 index.php,根據(jù)配置文件逊谋,Web Server知道這個不是靜態(tài)文件擂达,需要去找 PHP 解析器來處理,那么他會把這個請求簡單處理胶滋,然后交給PHP解析器板鬓。
當(dāng)Web Server收到 index.php 這個請求后悲敷,會啟動對應(yīng)的 CGI 程序,這里就是PHP的解析器俭令。接下來PHP解析器會解析php.ini文件后德,初始化執(zhí)行環(huán)境,然后處理請求抄腔,再以規(guī)定CGI規(guī)定的格式返回處理后的結(jié)果瓢湃,退出進(jìn)程,Web server再把結(jié)果返回給瀏覽器妓柜。這就是一個完整的動態(tài)PHP Web訪問流程箱季,接下來再引出這些概念涯穷,就好理解多了棍掐,
CGI:是 Web Server 與 Web Application 之間數(shù)據(jù)交換的一種協(xié)議。
FastCGI:同 CGI拷况,是一種通信協(xié)議作煌,但比 CGI 在效率上做了一些優(yōu)化。同樣赚瘦,SCGI 協(xié)議與 FastCGI 類似粟誓。
PHP-CGI:是 PHP (Web Application)對 Web Server 提供的 CGI 協(xié)議的接口程序。
PHP-FPM:是 PHP(Web Application)對 Web Server 提供的 FastCGI 協(xié)議的接口程序起意,額外還提供了相對智能一些任務(wù)管理鹰服。
WEB 中,
Web Server 一般指Apache揽咕、Nginx悲酷、IIS、Lighttpd亲善、Tomcat等服務(wù)器设易,
Web Application 一般指PHP、Java蛹头、Asp.net等應(yīng)用程序顿肺。
Module方式
在了解 CGI 之前,我們先了解一下Web server 傳遞數(shù)據(jù)的另外一種方法:PHP Module加載方式渣蜗。以 Apache 為例屠尊,在PHP Module方式中,是不是在 Apache 的配置文件 httpd.conf 中加上這樣幾句:
# 加入以下2句LoadModulephp5_module D:/php/php5apache2_2.dllAddTypeapplication/x-httpd-php .php# 修改如下內(nèi)容<IfModule dir_module>DirectoryIndexindex.php index.html</IfModule>
上面是 Windows 下安裝php和apache環(huán)境后手動配置耕拷,在linux下源碼安裝大致是這樣配置的:
# ./configure --with-mysql=/usr/local --with-apache=/usr/local/apache --enable-track-vars
所以知染,這種方式,他們的共同本質(zhì)都是用 LoadModule?來加載 php5_module斑胜,就是把php作為apache的一個子模塊來運行控淡。當(dāng)通過web訪問php文件時嫌吠,apache就會調(diào)用php5_module來解析php代碼。
那么php5_module是怎么來將數(shù)據(jù)傳給php解析器來解析php代碼的呢掺炭?答案是通過sapi辫诅。
我們再來看一張圖,詳細(xì)的說說apache 與 php 與 sapi的關(guān)系:
從上面圖中涧狮,我們看出了sapi就是這樣的一個中間過程炕矮,SAPI提供了一個和外部通信的接口,有點類似于socket者冤,使得PHP可以和其他應(yīng)用進(jìn)行交互數(shù)據(jù)(apache肤视,nginx等)。php默認(rèn)提供了很多種SAPI涉枫,常見的提供給apache和nginx的php5_module邢滑、CGI、FastCGI愿汰,給IIS的ISAPI困后,以及Shell的CLI。
所以衬廷,以上的apache調(diào)用php執(zhí)行的過程如下:
apache?->?httpd?->?php5_module?->?sapi?->?php
好了摇予。apache與php通過php5_module的方式就搞清楚了吧!
這種模式將php模塊安裝到apache中吗跋,所以每一次apache結(jié)束請求侧戴,都會產(chǎn)生一條進(jìn)程,這個進(jìn)程就完整的包括php的各種運算計算等操作跌宛。
在上圖中酗宋,我們很清晰的可以看到,apache每接收一個請求秩冈,都會產(chǎn)生一個進(jìn)程來連接php通過sapi來完成請求本缠,可想而知,如果一旦用戶過多入问,并發(fā)數(shù)過多丹锹,服務(wù)器就會承受不住了。
而且芬失,把mod_php編進(jìn)apache時楣黍,出問題時很難定位是php的問題還是apache的問題。
CGI
CGI(Common Gateway Interface)全稱是“通用網(wǎng)關(guān)接口”棱烂,WEB 服務(wù)器與PHP應(yīng)用進(jìn)行“交談”的一種工具租漂,其程序須運行在網(wǎng)絡(luò)服務(wù)器上。CGI可以用任何一種語言編寫,只要這種語言具有標(biāo)準(zhǔn)輸入哩治、輸出和環(huán)境變量秃踩。如php、perl业筏、tcl等憔杨。
WEB服務(wù)器會傳哪些數(shù)據(jù)給PHP解析器呢?URL蒜胖、查詢字符串消别、POST數(shù)據(jù)、HTTP header都會有台谢。所以寻狂,CGI就是規(guī)定要傳哪些數(shù)據(jù),以什么樣的格式傳遞給后方處理這個請求的協(xié)議朋沮。仔細(xì)想想蛇券,你在PHP代碼中使用的用戶從哪里來的。
也就是說朽们,CGI就是專門用來和 web 服務(wù)器打交道的怀读。web服務(wù)器收到用戶請求诉位,就會把請求提交給cgi程序(如php-cgi)骑脱,cgi程序根據(jù)請求提交的參數(shù)作應(yīng)處理(解析php),然后輸出標(biāo)準(zhǔn)的html語句苍糠,返回給web服服務(wù)器叁丧,WEB服務(wù)器再返回給客戶端,這就是普通cgi的工作原理岳瞭。
CGI的好處就是完全獨立于任何服務(wù)器拥娄,僅僅是做為中間分子。提供接口給apache和php瞳筏。他們通過cgi搭線來完成數(shù)據(jù)傳遞稚瘾。這樣做的好處了盡量減少2個的關(guān)聯(lián),使他們2變得更獨立姚炕。
但是CGI有個蛋疼的地方摊欠,就是每一次web請求都會有啟動和退出過程,也就是最為人詬病的fork-and-execute模式柱宦,這樣一在大規(guī)模并發(fā)下些椒,就死翹翹了。
FastCGI介紹
FastCGI簡單介紹
從根本上來說掸刊,F(xiàn)astCGI是用來提高CGI程序性能的免糕。類似于CGI,FastCGI也可以說是一種協(xié)議。
FastCGI像是一個常駐(long-live)型的CGI石窑,它可以一直執(zhí)行著牌芋,只要激活后,不會每次都要花費時間去fork一次松逊。它還支持分布式的運算, 即 FastCGI 程序可以在網(wǎng)站服務(wù)器以外的主機(jī)上執(zhí)行姜贡,并且接受來自其它網(wǎng)站服務(wù)器來的請求。
FastCGI是語言無關(guān)的棺棵、可伸縮架構(gòu)的CGI開放擴(kuò)展楼咳,其主要行為是將CGI解釋器進(jìn)程保持在內(nèi)存中,并因此獲得較高的性能烛恤。眾所周知母怜,CGI解釋器的反復(fù)加載是CGI性能低下的主要原因,如果CGI解釋器保持在內(nèi)存中缚柏,并接受FastCGI進(jìn)程管理器調(diào)度苹熏,則可以提供良好的性能、伸縮性币喧、Fail- Over特性等等轨域。
FastCGI的工作原理
FastCGI接口方式采用C/S結(jié)構(gòu),可以將HTTP服務(wù)器和腳本解析服務(wù)器分開杀餐,同時在腳本解析服務(wù)器上啟動一個或者多個腳本解析守護(hù)進(jìn)程干发。當(dāng)HTTP服務(wù)器每次遇到動態(tài)程序時,可以將其直接交付給FastCGI進(jìn)程來執(zhí)行史翘,然后將得到的結(jié)果返回給瀏覽器枉长。這種方式可以讓HTTP服務(wù)器專一地處理靜態(tài)請求,或者將動態(tài)腳本服務(wù)器的結(jié)果返回給客戶端琼讽,這在很大程度上提高了整個應(yīng)用系統(tǒng)的性能必峰。
Web Server啟動時載入FastCGI進(jìn)程管理器(Apache Module或IIS ISAPI等)
FastCGI進(jìn)程管理器自身初始化,啟動多個CGI解釋器進(jìn)程(可建多個php-cgi)钻蹬,并等待來自Web Server的連接吼蚁。
當(dāng)客戶端請求到達(dá)Web Server時,F(xiàn)astCGI進(jìn)程管理器選擇并連接到一個CGI解釋器问欠。Web server將CGI環(huán)境變量和標(biāo)準(zhǔn)輸入發(fā)送到FastCGI子進(jìn)程php-cgi肝匆。
FastCGI子進(jìn)程完成處理后,將標(biāo)準(zhǔn)輸出和錯誤信息從同一連接返回Web Server溅潜。當(dāng)FastCGI子進(jìn)程關(guān)閉連接時术唬,請求便告處理完成。FastCGI子進(jìn)程接著等待滚澜,并處理來自FastCGI進(jìn)程管理器(運行在Web Server中)的下一個連接粗仓。 在CGI模式中,php-cgi在此便退出了。
FastCGI與CGI特點:
對于CGI來說借浊,每一個Web請求PHP都必須重新解析php.ini塘淑、重新載入全部擴(kuò)展,并重新初始化全部數(shù)據(jù)結(jié)構(gòu)蚂斤。而使用FastCGI存捺,所有這些都只在進(jìn)程啟動時發(fā)生一次。一個額外的好處是曙蒸,持續(xù)數(shù)據(jù)庫連接(Persistent database connection)可以工作捌治。
由于FastCGI是多進(jìn)程,所以比CGI多線程消耗更多的服務(wù)器內(nèi)存纽窟,php-cgi解釋器每進(jìn)程消耗7至25兆內(nèi)存肖油,將這個數(shù)字乘以50或100就是很大的內(nèi)存數(shù)。
PHP-FPM介紹
要了解PHP-FPM臂港,就得先說說PHP-CGI森枪。
PHP-CGI就是PHP實現(xiàn)的自帶的FastCGI管理器。 雖然是php官方出品审孽,但是這丫的卻一點也不給力县袱,性能太差,而且也很麻煩不人性化佑力,主要體現(xiàn)在:
php-cgi變更php.ini配置后式散,需重啟php-cgi才能讓新的php-ini生效,不可以平滑重啟搓萧。
直接殺死php-cgi進(jìn)程杂数,php就不能運行了宛畦。
上面2個問題瘸洛,一直讓很多人病垢了很久,所以很多人一直還是在用?Module?方式次和。 直到 2004年一個叫 Andrei Nigmatulin的屌絲發(fā)明了PHP-FPM 反肋,這神器的出現(xiàn)就徹底打破了這種局面,這是一個PHP專用的 fastcgi 管理器踏施,它很爽的克服了上面2個問題石蔗,而且,還表現(xiàn)在其他方面更表現(xiàn)強(qiáng)勁畅形。
也就是說养距,PHP-FPM 是對于 FastCGI 協(xié)議的具體實現(xiàn),他負(fù)責(zé)管理一個進(jìn)程池日熬,來處理來自Web服務(wù)器的請求棍厌。目前,PHP5.3版本之后,PHP-FPM是內(nèi)置于PHP的耘纱。
因為PHP-CGI只是個CGI程序敬肚,他自己本身只能解析請求,返回結(jié)果束析,不會進(jìn)程管理艳馒。所以就出現(xiàn)了一些能夠調(diào)度 php-cgi 進(jìn)程的程序,比如說由lighthttpd分離出來的spawn-fcgi员寇。同樣弄慰,PHP-FPM也是用于調(diào)度管理PHP解析器php-cgi的管理程序。
PHP-FPM通過生成新的子進(jìn)程可以實現(xiàn)php.ini修改后的平滑重啟蝶锋。
總結(jié)
最后曹动,我們來總結(jié)一下,這些技術(shù)經(jīng)過不斷的升級牲览,可以解決什么問題(不然也不會升級嘛)墓陈。
所以,如果要搭建一個高性能的PHP WEB服務(wù)器第献,目前最佳的方式是Apache/Nginx+FastCGI+PHP-FPM(+PHP-CGI)方式了贡必,不要再使用 Module加載或者 CGI 方式啦:)