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); }
Web Server隔離:FastCGI後端和Web Server運行在不同的進程中,後端的任何故障不會導致Web Server掛掉。
專利:沒有Apache mod_php之類的私有API的知識產權問題。
擴展:FastCGI後端和Web Server通過Socket進行通信,兩者可以分佈式部署並方便進行橫向擴展。
所以FastCGI一推出就幾乎獲得了所有主流Web Server的支持,Apache、Lighttpd、IIS、Cherokee……
題主說的php-fpm就是一種FastCGI的後端實現。
But,事情總是還有改進的餘地的,FastCGI這套工作模式實際上沒有什麼太大缺陷,但是有些不安分的Python程序猿覺得,FastCGI標準下寫異步的Web服務還是不太方便,如果能夠收到請求後CGI端去處理,處理完畢後通過Callback回調來返回結果,那樣豈不是很Coooool?!所以WSGI就被創造出來了:
WSGI(Web Server Gateway Interface)
Web服務器網關接口(Web Server Gateway Interface,縮寫爲WSGI)是爲Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口。
當Web Server收到一個請求後,可以通過Socket把環境變量和一個Callback回調函數傳給後端Web應用,Web應用在完成頁面組裝後通過Callback把內容返回給Web Server。這樣做的優點有很多:
異步化,通過Callback將Web請求的工作拆解開,可以很方便的在一個線程空間裏同時處理多個Web請求。
方便進行各種負載均衡和請求轉發,不會造成後端Web應用阻塞。
Web開發有3P:Perl、Python、PHP。Perl是1987年發佈的,Python是1989年,PHP是1995年。CGI標準提出的時候正是Perl如日中天的時候,所以CGI的提出當時也是主要爲了解決Perl作爲Web編程語言的需求。熟悉正則(regex)的程序員可能知道正則的事實標準叫做pcre(Perl兼容正則表達式,Perl Compatible Regular Expressions),這也從一個側面體現了Perl作爲一個古老的語言在當時對各種業界標準的影響。
PHP-FPM 是一個實現了 FastCgi 的程序,而FastCgi給Cgi提供了通道。