簡單了解下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這個編譯參數即可。