先說一個重要結論
- nginx+PHP-FPM在高併發情況下可能會達到Apache+mod_php5的5~10倍,現在nginx+PHP-FPM使用的人越來越多。
CGI
- CGI的英文是(COMMON GATEWAY INTERFACE)公共閘道器介面,伺服器並不能直接執行 php,asp這樣的檔案,它的作用就是幫助伺服器與語言通訊,這裡就是nginx和php進行通訊,因為nginx和php的語言不通,因此需要一個溝通轉換的過程,而CGI就是這個溝通的協議。
- nginx伺服器在接受到瀏覽器傳遞過來的資料後,如果請求的是靜態的頁面或者圖片等無需動態處理的則會直接根據請求的url找到其位置然後返回給瀏覽器,這裡無需php參與,但是如果是一個動態的頁面請求,這個時候nginx就必須與php通訊,這個時候就會需要用到cgi協議,將請求資料轉換成php能理解的資訊,然後php根據這些資訊返回的資訊也要通過cgi協議轉換成nginx可以理解的資訊,最後nginx接到這些資訊再返回給瀏覽器。
fast-cgi
-
傳統的cgi協議在每次連線請求時,會開啟一個程式進行處理,處理完畢會關閉該程式,因此下次連線,又要再次開啟一個程式進行處理,因此有多少個連線就有多少個cgi程式,這也就是為什麼傳統的cgi會顯得緩慢的原因,因此過多的程式會消耗資源和記憶體。
-
而fast-cgi則是一個程式可以處理多個請求,和上面的cgi協議完全不一樣,cgi是一個程式只能處理一個請求,這樣就會導致大量的cgi程式,因此會給伺服器帶來負擔。
php-cgi:
- php-cgi是php提供給web serve也就是http前端伺服器的cgi協議介面程式,當每次接到http前端伺服器的請求都會開啟一個php-cgi程式進行處理,而且開啟的php-cgi的過程中會先要過載配置,資料結構以及初始化執行環境,如果更新了php配置,那麼就需要重啟php-cgi才能生效,例如phpstudy就是這種情況。
php-fpm:
- php-fpm是php提供給web serve也就是http前端伺服器的fastcgi協議介面程式,它不會像php-cgi一樣每次連線都會重新開啟一個程式,處理完請求又關閉這個程式,而是允許一個程式對多個連線進行處理,而不會立即關閉這個程式,而是會接著處理下一個連線。它可以說是php-cgi的一個管理程式,是對php-cgi的改進。
- php-fpm會開啟多個php-cgi程式,並且php-fpm常駐記憶體,每次web serve伺服器傳送連線過來的時候,php-fpm將連線資訊分配給下面其中的一個子程式php-cgi進行處理,處理完畢這個php-cgi並不會關閉,而是繼續等待下一個連線,這也是fast-cgi加速的原理,但是由於php-fpm是多程式的,而一個php-cgi基本消耗7-25M記憶體,因此如果連線過多就會導致記憶體消耗過大,引發一些問題,例如nginx裡的502錯誤。
同時php-fpm還附帶一些其他的功能:
- 例如平滑過渡配置更改,普通的php-cgi在每次更改配置後,需要重新啟動才能初始化新的配置,而php-fpm是不需要,php-fpm分將新的連線傳送給新的子程式php-cgi,這個時候載入的是新的配置,而原先正在執行的php-cgi還是使用的原先的配置,等到這個連線後下一次連線的時候會使用新的配置初始化,這就是平滑過渡。
示意圖
FastCGI的整個工作流程
- Web Server啟動時載入FastCGI程式管理器(IIS ISAPI或Apache Module)
- 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在此便退出了。