簡單了解下CGI、FastCGI和php-fpm的概念和區別和運行原理
- 2019 年 10 月 10 日
- 筆記
什麼是CGI?
CGI(Common Gateway Interface),公共網關接口,它是Web服務器與外部應用程序(CGI程序)之間傳遞信息的接口標準。通過CGI接口,Web服務器就能夠獲取客戶端提交的信息,並轉交給服務器端的CGI程序處理,最後返回結果給客戶端。
也就是說,CGI實際上是一個接口標準。我們通常所說的CGI是指CGI程序,即實現了CGI接口標準的程序。
只要某種語言具有標準輸入、輸出和環境變量,如perl、php、C等,就可以用來編寫CGI程序。
CGI程序的工作方式:
Web服務器一般只處理靜態文件請求(如 jpg、htm、html),如果碰到一個動態腳本請求(如php),web服務器主進程,就fork出一個新的進程來啟動CGI程序,也就是說將動態腳本請求交給CGI程序來處理。啟動CGI程序需要一個過程,比如,讀取配置文件,加載擴展等。CGI程序啟動後,就會解析動態腳本,然後將結果返回給Web服務器,最後Web服務器再將結果返回給客戶端,剛才fork的進程也會隨之關閉。
這樣,每次用戶請求動態腳本,Web服務器都要重新fork一個新進程,去啟動CGI程序,由CGI程序來處理動態腳本,處理完後進程隨之關閉。
這種工作方式的效率是非常低下的。
PHP 解釋器是否嵌入 Web 服務器進程內部執行
後來,出現了一種比較高效的方式:Web服務器內置模塊。例如,apache的mod_php模塊。將php解釋器做成模塊,然後加載到apache服務器中。
這樣,apache服務器在啟動的時候,就會同時啟動php模塊。當客戶端請求php文件時,apache服務器就不用再fork出一個新進程來啟動php解釋器,而是直接將php文件交給運行中的php模塊處理。顯然,這種方式下,效率會比較高。
由於在apache服務器啟動時,才會讀取php的配置文件,加載php模塊,在apache的運行過程中。不會再重新讀取php的配置文件。所以,每次我們修改了php的配置文件後,必須重啟apache,新的php配置文件才會生效。
mod_php 通過嵌入 PHP 解釋器到 Apache 進程中,只能與 Apache 配合使用,而 cgi 和 fast-cgi 以獨立的進程的形式出現,只要對應的Web服務器實現 cgi 或者 fast-cgi 協議,就能夠處理 PHP 請求。mod_php 這種嵌入的方式最大的弊端就是內存佔用大,不論是否用到 PHP 解釋器都會將其加載到內存中,典型的就是處理CSS、JS之類的靜態文件是完全沒有必要加載解釋器。
什麼是FastCGI?
FastCGI就像是一個常駐(long-live)型的CGI程序,它可以一直運行着。FastCGI程序也可以和Web服務器分別部署在不同的主機上,它還可以接受來自其他Web服務器的請求。
FastCGI也是語言無關的。其主要行為是將CGI解釋器進程保持在內存中並因此獲得高效的性能。眾所周知,CGI解釋器的反覆加載是CGI性能低下的主要原因。
FastCGI是一種進程管理工具,它可以在內存中管理CGI進程。
FastCGI進程管理器需要單獨啟動。啟動FastCGI後,會生成一個FastCGI主進程和多個子進程(子進程其實就是CGI解釋器進程)。
當客戶端請求Web服務器上的動態腳本時,Web服務器會將動態腳本通過TCP協議交給FastCGI主進程,FastCGI主進程根據情況,安排一個空閑的子進程來解析動態腳本,處理完成後將結果返回給Web服務器,Web服務器再將結果返回給客戶端。該客戶端請求處理完畢後,FastCGI子進程並不會隨之關閉,而是繼續等待主進程安排工作任務。
FastCGI的重要特點:
1、FastCGI是HTTP服務器和動態腳本語言間通信的接口或者工具。
2、FastCGI優點是把動態語言解析和HTTP服務器分離開來。
3、Nginx、Apache、Lighttpd以及多數動態語言都支持FastCGI。
4、FastCGI接口方式採用C/S架構,分為客戶端(HTTP服務器)和服務端(動態語言解析服務器)。
5、PHP動態語言服務端可以啟動多個FastCGI的守護進程。
6、HTTP服務器通過FastCGI客戶端和動態語言FastCGI服務端通信。
原理圖及運行過程:
一、Web Server啟動時載入FastCGI進程管理器(Apache Module或IIS ISAPI等)
二、FastCGI進程管理器自身初始化,啟動多個CGI解釋器進程(可建多個php-cgi),並等待來自Web Server的連接。
三、當客戶端請求到達Web Server時,FastCGI進程管理器選擇並連接到一個CGI解釋器。Web server將CGI環境變量和標準輸入發送到FastCGI子進程php-cgi。
四、FastCGI子進程完成處理後,將標準輸出和錯誤信息從同一連接返回Web Server。當FastCGI子進程關閉連接時,請求便告處理完成。FastCGI子進程接着等待,並處理來自FastCGI進程管理器(運行在Web Server中)的下一個連接。 在CGI模式中,php-cgi在此便退出了
什麼是php-fpm?
fpm是FastCGI Process Manager的縮寫,那麼,fpm就是FastCGI進程管理器的簡稱。
php-fpm就是php中的FastCGI進程管理器。
對於php5.3之前的版本來說,php-fpm是一個第三方的補丁包,旨在將FastCGI進程管理整合進PHP包中。
在php5.3之後的版本中,php-fpm不再是第三方的包,它已經被集成到php的源碼中了。php-fpm提供了更好的PHP進程管理方式,可以有效控制內存和進程、可以平滑重載PHP配置,比spawn-fcgi具有更多優點,所以php-fpm被PHP官方收購了。
php-fpm的管理對象是php-cgi。但不能說php-fpm是fastcgi進程的管理器,因為前面說了fastcgi是個協議,似乎沒有這麼個進程存在,就算存在php-fpm也管理不了他(至少目前是)。 有的說,php-fpm是php內核的一個補丁以前是對的。因為最開始的時候php-fpm沒有包含在PHP內核裏面,要使用這個功能,需要找到與源碼版本相同的php-fpm對內核打補丁,然後再編譯。後來PHP內核集成了PHP-FPM之後就方便多了,使用–enalbe-fpm這個編譯參數即可。