來源:互聯網
上載者:User
關鍵字
php
fastcgi
apache
module
nginx
在apache裡,可以以php5_module模組的方式調用PHP,而在nginx裡面,則需要通過php-fpm來調用,這兩種調用方式有什麼不同?另外,它們跟cgi,fastcgi有什麼關係?
回複內容:
上面的回答多少都有些問題吧。
CGI是HTTP Server和一個獨立的進程之間的協議,把HTTP Request的Header設定成進程的環境變數,HTTP Request的本文設定成進程的標準輸入,而進程的標準輸出就是HTTP Response包括Header和本文。
FASTCGI是和HTTP協議類似的概念。無非就是規定了在同一個TCP串連裡怎麼同時傳多個HTTP串連。這實際上導致了個問題,有個HTTP串連傳個大檔案不肯讓出FASTCGI串連,在同一個FASTCGI串連裡的其他HTTP串連就傻了。所以Lighttpd? 引入了 X-SENDFILE 。
php-fpm就相當於是Apache+mod_php。無非php-fpm內建了FASTCGI Server,而Apache是HTTP Server。
那個WSGI和這個問題沒啥關係吧。WSGI這個只是Python內部的一個介面。無論你前面是FASTCGI,HTTP,SCGI,uWSGI等協議,你的FASTCGI/HTTP/SCGI/uWSGI Server都以相同的參數格式去調用一個函數,這樣你用Python寫的Web應用並不需要修改代碼,就可以運行在不同的Server後面了。無非CGI協議是進程間的,而WSGI是進程內的。b本屌絲路過 也來吹吹牛逼
1. 一般web伺服器接受到瀏覽器的請求時,如果是靜態資源的話就直接將其返回給瀏覽器,如果是動態資源的話那就沒有現成的資源返回了,那這個時候cgi就出場了
2. cgi可以理解為一種協議or一類處理常式,就是動態去組建檔案,從程式上來理解就是web伺服器exec這樣一個進程,然後交給他一些輸入參數,他就慢慢的處理完後把結果返回給web伺服器,那從協議層面來說cgi協議就是規範了web伺服器和cgi程式的一些輸入輸出參數的含義
3.所以可以有很多不同的cgi程式,別可以執行php指令碼的or可以執行python指令碼的,只要符合這類規範就能供web伺服器調用,當然它的缺點就是每次都需要去啟動這個cgi程式,這會使得處理速度很慢
4.針對這種缺陷加以改進就成了fastcgi,同樣的他也可以理解為一種協議or一個程式,它跟cgi的不同就是不需要每次去exec,它會事先啟動起來,作為一個cgi的管理伺服器存在,預先啟動一系列的子進程來等待處理,然後等待web伺服器發過來的請求,一旦接受到請求就交由子進程處理,這樣由於不需要在接受到請求後啟動cgi,會快很多。
5.phpfpm是php對fastcgi的一種具體實現,它的啟動後會建立多個cgi子進程,然後主進程負責管理子進程,同時它對外提供一個socket,那web伺服器當要轉寄一個動態請求時只需要按照fastcgi協議要求的格式將資料發往這個socket的就可以了,那phpfpm建立的子進程去爭搶這個socket串連,誰搶到了誰處理並將結果返回給web伺服器,那phpfpm主進程幹什麼了?比方說其中一個子進程異常退出了怎麼辦,那phpfpm會去監控他一旦發現一個cgi子進程就會又啟動一個,還有其他諸多管理功能
6 phpfpm作為一個獨立的進程存在 通過socket與nginx建立串連,而mod_php 是作為一個模組被載入進了apache伺服器,同時他們兩作為cgi調度管理器,他們對其管理的方式也不一樣
就說這麼多了通俗的可以把伺服器看作餐廳,使用者請求看作來用餐的顧客,伺服器處理請求看作解決顧客的就餐問題(響應輸出一份飯)。
伺服器上靜態資源看作已做好的飯,只要放到餐盒裡就可以返回給顧客,動態資源需要廚房大廚現成做份再放到餐盒裡返回給顧客。
php_mod這個大廚有個特點,看見有顧客進門就點火,不管顧客要不要現做的,有點浪費資源
php_fpm這個大廚有好多小弟一直點著火(多個處理進程),等有顧客說要現做,大廚就安排小弟做份返回給客戶
cgi也是個大廚,不過他等到顧客要現做,他才點火,做飯,然後熄火。等待下一個要現做的到來
fastcgi呢就是個大廚雇了一幫小弟,專門做需要現場做的飯,大廚只管指派任務,小弟真正操鍋做飯這個問題可以分兩個層面討論:
1. PHP 解譯器是否嵌入 Web 服務器進程內部執行
mod_php 通過嵌入 PHP 解譯器到 Apache 進程中,只能與 Apache 配合使用,而 cgi 和 fast-cgi 以獨立的進程的形式出現,只要對應的Web伺服器實現 cgi 或者 fast-cgi 協議,就能夠處理 PHP 請求。
mod_php 這種嵌入的方式最大的弊端就是記憶體佔用大,不論是否用到 PHP 解譯器都會將其載入到記憶體中,典型的就是處理CSS、JS之類的靜態檔案是完全沒有必要載入解譯器。
2. 單個進程處理的請求數量
mod_php 和 fast-cgi 的模式在每個進程的生命週期內能夠處理多個請求,而 cgi 的模式處理一個請求就馬上銷毀進程,在高並發的情境下 cgi 的效能非常糟糕。
綜上,如果對效能有極高的要求,可以將靜態請求和動態請求分開,這時 Nginx + php-fpm 是比較好的選擇。
PS: cgi、fastcgi 通常指 Web 服務器與解譯器通訊的協議規範,而 php-fpm 是 fastcgi 協議的一個實現。
CGI(Common Gateway Interface)
最初,CGI 是在 1993 年由美國國家超級電腦應用中心(NCSA)為 NCSA HTTPd Web 服務器開發的。
這個 Web 服務器使用了 UNIX shell 環境變數 來儲存從 Web 服務器傳遞出去的參數,然後產生一個運行 CGI 的獨立進程。CGI的第一個實現是 Perl 寫的[1]。
- 效率低下:每一個串連 fork 一個進程處理。
- 功能十分有限:CGI只能收到一個請求,輸出一個響應。很難在CGI體系去對Web請求的控制,例如:使用者認證等。
正因為這些問題,在CGI誕生後的很長一段時間,各種Web Server都還是採用API這種強綁定的方式去支援Web開發,其中Apache的mod_php就屬於這種方式。所以後面就有大神提出了FastCGI標準。
FastCGI(Fast Common Gateway Interface)
FastCGI使用進程/線程池來處理一連串的請求。這些進程/線程由FastCGI伺服器管理,而不是Web伺服器。 當進來一個請求時,Web伺服器把環境變數和這個頁面請求通過一個Socket長串連傳遞給FastCGI進程。所以FastCGI有如下的優點:
- 效能:通過進程/線程池規避了CGI開闢新的進程的開銷。
- 相容:非常容易改造現有CGI標準的程式。
- 語言無關:FastCGI是一套標準,理論上講只要能進行標準輸出(stdout)的語言都可以作為FastCGI標準的Web後端。
下面是一個簡單FastCGI後端的虛擬碼
void main(void){int count = 0; while(FCGI_Accept() >= 0) { printf(“Content-type: text/html\r\n”); printf(“\r\n”); printf(“Hello world!\r\n”); printf(“Request number %d.”, count++); }exit(0);}
CGI 中文翻譯是通用閘道介面,它是一種通訊協定,讓指令碼語言(比如PHP)具備和 HTTP Server 互動的能力。
FastCGI 是對 CGI 的一種改良,解決了 CGI 協議的一些效能問題,在 PHP 平台被廣泛採用。類似的東西還有 WSGI。
php-fpm 就是FastCGI 的一種實現,附帶了進程管理的功能。CGI看RFC3875:https://www.ietf.org/rfc/rfc3875
FastCGI看:FastCGI Specification
總的來說FastCGI是對CGI的效能改進,規範上有一些差異但是不大,與瀏覽器的通訊規範是一致的。
PHP不瞭解。
PHP 解譯器的執行,主要有三者模式,mod_php、CGI、FastCGI。
- mode_php 是Apache 的一個模組,把PHP 解譯器嵌入到Apache 進程中。
- CGI 和FastCGI 分別是一種協議。Web Server 實現了CGI 或FastCGI 協議的相應的應用程式(以下簡稱CGI 或FastCGI),就可以啟動PHP 解譯器處理PHP 請求。它們都是以獨立進程的形式存在。
- mode_php 和FastCGI 在 單個進程中可以處理多個請求,CGI 在單個進程中只能處理一個請求。
php-cgi 是一種
CGI 協議的實現。
- php-cgi 其實就是PHP 解析器。
- 在CGI 模式時,當Web Server 收到 xx/index.php 請求時,會啟動php-cgi,php-cgi 會解析php.ini 檔案,初始化環境,然後根據請求參數進行處理,再返回處理後的結果。(都是以CGI 協議規範來進行)
- php-cgi 在每個請求時都會啟動一個進程,然後讀取php.ini 進行解析,可想而知效率相對比較低。
- php-cgi 無法實現平滑重啟。修改php.ini 配置後,後面啟動的php-cgi 程式還是不會感知。
php-fpm
即FastCGI Process Management,是一種
FastCGI 協議的實現。
- 當請求到來時,php-fpm 啟動並讀取php.ini 檔案完成初始化環境,然後啟動一個master,再啟動多個worker。當請求過來時,master 會傳遞給一個worker,然後等待下一個請求。php-fpm 會動態配置worker 的數量。
- 一個php-fpm 進程可以處理多個請求,會啟動多個php-cgi 程式。
- php-fpm 可以實現平衡重啟。修改php.ini 後,當啟用新的worker 會使用新的配置。
CGI,Common Gateway Interface,通用閘道介面。將使用者的指令通過它遞交給後台進行處理。可以理解為一種通用的協議,能夠標準化使用者指令,方便背景程式進行後續的處理。
FastCGI根據協議將CGI進行封裝,與外部程式如nginx進行通訊。一般擁有主從進程。FastCGI可以管理多種語言的CGI,比如題主提到的PHP,另外還有Python、Ruby等。可以理解為一種CGI的成熟模型。
而PHP-FPM是一個很好地實現了FastCGI的程式,後來被PHP收入官方項目中了。可以理解為FastCGI的管理器。穩定地管理FastCGI進程。