天天看點

關于CGI 和 PHP-FPM需要弄清的

原文位址: 關于CGI 和 PHP-FPM需要弄清的

首先我們引入一些概念,搞清楚 CGI 和 FastCGI

CGI

通用網關接口(Common Gateway Interface/CGI)是一種重要的網際網路技術,可以讓一個用戶端,從網頁浏覽器向執行在網絡伺服器上的程式請求資料。CGI描述了伺服器和請求處理程式之間傳輸資料的一種标準。

FastCGI

快速通用網關接口(Fast Common Gateway Interface/FastCGI)是一種讓互動程式與Web伺服器通信的協定。FastCGI是早期通用網關接口(CGI)的增強版本。

FastCGI緻力于減少網頁伺服器與CGI程式之間互動的開銷,進而使伺服器可以同時處理更多的網頁請求。

好現在明白了

CGI 和 FastCGI 是一種通信協定規範,不是一個實體

我們平常需要用詞規範,是CGI 還是 CGI程式

CGI 程式和FastCGI程式,是指實作這兩個協定的程式,可以是任何語言實作這個協定的。(PHP-CGI 和 PHP-FPM就是實作FastCGI的程式)

為什麼推薦使用FastCGI程式

除了上面對兩個協定的描述外,這裡再補充下他們實作的程式的差別。

關于CGI程式

CGI使外部程式與Web伺服器之間互動成為可能。CGI程式運作在獨立的程序中,并對每個Web請求建立一個程序,這種方法非常容易實作,但效率很差,難以擴充。面對大量請求,程序的大量建立和消亡使作業系統性能大大下降。此外,由于位址空間無法共享,也限制了資源重用。

關于FastCGI程式

與為每個請求建立一個新的程序不同,FastCGI使用持續的程序來處理一連串的請求。這些程序由FastCGI伺服器管理,而不是web伺服器。 當進來一個請求時,web伺服器把環境變量和這個頁面請求通過一個socket比如FastCGI程序與web伺服器(都位于本地)或者一個TCP connection(FastCGI程序在遠端的server farm)傳遞給FastCGI程序。

FastCGI為了提高CGI的效率而存在的。

PHP-CGI 和 PHP-FPM的差別

PHP-CGI是PHP自帶的FastCGI管理器。啟動PHP-CGI,使用如下指令:

php-cgi -b 127.0.0.1:9000

php-cgi與php-fpm一樣,也是一個fastcgi程序管理器,php-cgi的問題在于 1、php-cgi變更php.ini配置後需重新開機php-cgi才能讓新的php-ini生效,不可以平滑重新開機 2、直接殺死php-cgi程序,php就不能運作了。(PHP-FPM和Spawn-FCGI就沒有這個問題,守護程序會平滑從新生成新的子程序。) 針對php-cgi的不足,php-fpm應運而生。

PHP-FPM 的管理對象是php-cgi。使用PHP-FPM來控制PHP-CGI的FastCGI程序

Nginx 如何調用PHP

web server(比如說nginx)隻是内容的分發者。比如,如果請求/index.html,那麼web server會去檔案系統中找到這個檔案,發送給浏覽器,這裡分發的是靜态資料。好了,如果現在請求的是/index.php,根據配置檔案,nginx知道這個不是靜态檔案,需要去找PHP解析器來處理,那麼他會把這個請求簡單處理後交給PHP解析器。Nginx會傳哪些資料給PHP解析器呢?url要有吧,查詢字元串也得有吧,POST資料也要有,HTTP header不能少吧,好的,CGI就是規定要傳哪些資料、以什麼樣的格式傳遞給後方處理這個請求的協定。仔細想想,你在PHP代碼中使用的使用者從哪裡來的。

當web server收到/index.php這個請求後,會啟動對應的CGI程式,這裡就是PHP的解析器。接下來PHP解析器會解析php.ini檔案,初始化執行環境,然後處理請求,再以規定CGI規定的格式傳回處理後的結果,退出程序。web server再把結果傳回給浏覽器。

Apache如何調用PHP

Apache 有個mod_php 擴充。php是apache的一個外挂程式,必須依靠web伺服器才可以運作。當用戶端浏覽器觸發事件—>url 送出到apache伺服器—->apache伺服器根據php程式的特點判斷是php程式,送出給php引擎程式—>php引擎程式解析并讀取資料庫生成相應的頁面

FastCGI運作模式分析:

FastCGI的工作原理是:

(1)、Web Server 啟動時載入FastCGI程序管理器【PHP的FastCGI程序管理器是PHP-FPM(php-FastCGI Process Manager)】(IIS ISAPI或Apache Module);

(2)、FastCGI程序管理器自身初始化,啟動多個CGI解釋器程序 (在任務管理器中可見多個php-cgi.exe)并等待來自Web Server的連接配接。

(3)、當用戶端請求到達Web Server時,FastCGI程序管理器選擇并連接配接到一個CGI解釋器。Web server将CGI環境變量和标準輸入發送到FastCGI子程序php-cgi.exe。

(4)、FastCGI子程序完成處理後将标準輸出和錯誤資訊從同一連接配接傳回Web Server。當FastCGI子程序關閉連接配接時,請求便告處理完成。FastCGI子程序接着等待并處理來自FastCGI程序管理器(運作在 WebServer中)的下一個連接配接。 在正常的CGI模式中,php-cgi.exe在此便退出了。

在上述情況中,你可以想象 CGI通常有多慢。每一個Web請求PHP都必須重新解析php.ini、重新載入全部dll擴充并重初始化全部資料結構。使用FastCGI,所有這些 都隻在程序啟動時發生一次。一個額外的好處是,持續資料庫連接配接(Persistent database connection)可以工作。

為什麼要使用FastCGI,而不是多線程CGI解釋器?

這可能出于多方面的考慮,例如:

(1)、你無論如何也不能在windows平台上穩定的使用多線程CGI解釋器,無論是IIS ISAPI方式還是APACHE Module方式,它們總是運作一段時間就崩潰了。奇怪麼?但是确實存在這樣的情況!

當然,也有很多時候你能夠穩定的使用多線程CGI解釋器,但是,你有可能發現網頁有時候會出現錯誤,無論如何也找不到原因,而換用FastCGI方式 時這種錯誤的機率會大大的降低。我也不清楚這是為什麼,我想獨立位址空間的CGI解釋器可能終究比共享位址空間的形式來得穩定一點點。

(2)、性能!性能?可能麼,難道FastCGI比多線程CGI解釋器更快?但有時候确實是這樣,隻有測試一下你的網站,才能最後下結論。原因嘛,我覺得 很難講,但有資料說在Zend WinEnabler的時代,Zend原來也是建議在Windows平台下使用FastCGI而不是IIS ISAPI或Apache Module,不過現在Zend已經不做這個産品了。

FastCGI 模式運作PHP 的優點:

以 FastCGI 模式運作 PHP 有幾個主要的好處。首先就是 PHP 出錯的時候不會搞垮 Apache,隻是 PHP 自己的程序當掉(但 FastCGI 會立即重新啟動一個新 PHP 程序來代替當掉的程序)。其次 FastCGI 模式運作 PHP 比 ISAPI 模式性能更好(我本來用 ApacheBench 進行了測試,但忘了儲存結果,大家有興趣可以自己測試)。

參考:

FastCGI - 維基百科,自由的百科全書

什麼是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI?

apache php的幾種運作方式(cgi,fastcgi…)