PHP 執行模式

Jochen發表於2018-04-25

 SAPI

  這裡所說的 PHP 執行模式, 其實指的是 SAPI (Server Application Programming Interface,服務端應用程式設計埠 )。SAPI 為 PHP 提供了一個和外部通訊的介面, PHP 就是通過這個介面來與其它的應用進行資料互動的。針對不同的應用場景, PHP 也提供了多種不同的 SAPI ,常見的有:apache、apache2filter、apache2handler、cli、cgi、embed 、fast-cgi、isapi 等等。

php_sapi_name() — 返回 web 伺服器和 PHP 之間的介面型別。可能返回的值包括了 aolserver、apache、 apache2filter、apache2handler、 caudium、cgi (直到 PHP 5.3), cgi-fcgi、cli、 cli-server、 continuity、embed、fpm-fcgi、 isapi、litespeed、 milter、nsapi、 phttpd、pi3web、roxen、 thttpd、tux 和 webjames。

  目前 PHP 內建的很多 SAPI 實現都已不再維護或者變的有些非主流了,PHP 社群目前正在考慮將一些 SAPI 移出程式碼庫。 社群對很多功能的考慮是除非真的非常必要,或者某些功能已近非常通用了,否則就在 PECL 庫中。

  接下來會對其中五個比較常見的執行模式進行說明。

 CLI 模式

  CLI( Command Line Interface ), 也就是命令列介面,PHP 預設會安裝。通過這個介面,可以在 shell 環境下與 PHP 進行互動 。在終端裡輸入 php -v,會得到類似下圖的結果(安裝了 PHP 前提下):

  因為有 CLI 的存在,我們可以直接在終端命令列裡執行 PHP 指令碼,就像使用 shell、Python 那樣,不用依賴於 WEB 伺服器。比如 Laravel 框架中的 Artisan 命令列工具,它其實就是一個 PHP 指令碼,用來幫助我們快速構建 Laravel 應用的。

 CGI 模式

CGI(Common Gateway Interface,通用閘道器介面)是一種重要的網際網路技術,可以讓一個客戶端,從網頁瀏覽器向執行在網路伺服器上的程式請求資料。CGI 描述了伺服器和請求處理程式之間傳輸資料的一種標準。

  WEB 伺服器只是內容的分發者。比如 Nginx,如果客戶端請求了 /index.html,那麼 Nginx 會去檔案系統中找到這個檔案,傳送給瀏覽器,這裡分發的是靜態資料;如果客戶端現在請求的是 /index.php,根據配置檔案,Nginx 知道這個不是靜態檔案,需要去找 PHP 解析器來處理,那麼它會把這個請求經過簡單處理後交給PHP 解析器。Nginx 會傳哪些資料給 PHP 解析器呢?url 要有吧,查詢字串也得有吧,POST 資料也要有,HTTP 請求頭 不能少吧,好的,CGI 就是規定要傳哪些資料、以什麼樣的格式傳遞給後方處理這個請求的協議。

  CGI 模式執行原理:當 Nginx 收到瀏覽器 /index.php 這個請求後,首先會建立一個對應實現了 CGI 協議的程式,這裡就是 php-cgi(PHP 解析器)。接下來 php-cgi 會解析 php.ini 檔案,初始化執行環境,然後處理請求,再以 CGI 規定的格式返回處理後的結果,退出程式。最後,Nginx 再把結果返回給瀏覽器。整個流程就是一個 Fork-And-Execute 模式。當使用者請求數量非常多時,會大量擠佔系統的資源如記憶體、CPU 時間等,造成效能低下。所以在用 CGI 方式的伺服器下,有多少個連線請求就會有多少個 CGI 子程式,子程式反覆載入是 CGI 效能低下的主要原因。

  CGI 模式的好處就是完全獨立於任何伺服器,僅僅是做為一箇中介:提供介面給 WEB 伺服器和指令碼語言或者是完全獨立程式語言。它們通過 CGI 協議搭線來完成資料傳遞。這樣做的好處了儘量減少它們之間的關聯,使得各自更加獨立、互不影響。

  CGI 模式已經是比較古老的模式了,這幾年都很少用了。

 FastCGI 模式

FastCGI(Fast Common Gateway Interface,快速通用閘道器介面)是一種讓互動程式與 Web 伺服器通訊的協議。FastCGI 是早期通用閘道器介面(CGI)的增強版本。FastCGI 致力於減少網頁伺服器與 CGI 程式之間互動的開銷,從而使伺服器可以同時處理更多的網頁請求。

  根據定義可以知道,FastCGI 也是一種協議,實現了 FastCGI 協議的程式,更像是一個常駐型(long-live)的 CGI 協議程式,只要啟用後,它可以一直執行著,不會每次都要花費時間去 fork 一次。

  FastCGI 模式執行原理:FastCGI 程式管理器啟動之後,首先會解析 php.ini 檔案,初始化執行環境,然後會啟動多個 CGI 協議直譯器守護程式 (程式管理中可以看到多個 php-cig 或 php-cgi.exe),並等待來自 WEB 伺服器的連線;當客戶端請求到達 WEB 伺服器時,FastCGI 程式管理器會選擇並連線到一個 CGI 直譯器, WEB 伺服器將 CGI環境變數和標準輸入傳送到 FastCGI 的子程式 php-cgi 中; php-cgi 子程式完成處理後便將標準輸出和錯誤資訊返回給 WEB 伺服器;此時 php-cgi 子程式就會關閉連線,該請求便處理結束,接著繼續等待並處理來自 FastCGI 程式管理器的下一個請求連線。

  FastCGI 模式採用了 C/S 結構,可以將 WEB 伺服器和指令碼解析伺服器分開,同時在指令碼解析伺服器上啟動一個或者多個指令碼解析守護程式。當 WEB 伺服器每次遇到動態程式時,可以將其直接交付給 FastCGI 程式來執行,然後將得到的結果返回給瀏覽器。這種方式可以讓 WEB 伺服器專一地處理靜態請求或者將動態指令碼伺服器的結果返回給客戶端,這在很大程度上提高了整個應用系統的效能。

  另外,在 CGI 模式下,php-cgi 在 php.ini 配置變更後,需要重啟 php-cgi 程式才能讓新的 php-ini 配置生效,不可以平滑重啟。而在 FastCGI 模式下,PHP-FPM 可以通過生成新的子程式來實現 php.ini 修改後的平滑重啟。

PHP-FPM(PHP-FastCGI Process Manager)是 PHP 語言中實現了 FastCGI 協議的程式管理器,由 Andrei Nigmatulin 編寫實現,已被 PHP 官方收錄並整合到核心中。

  FastCGI 模式的優點:

  1. 從穩定性上看,FastCGI 模式是以獨立的程式池來執行 CGI 協議程式,單獨一個程式死掉,系統可以很輕易的丟棄,然後重新分配新的程式來執行邏輯;
  2. 從安全性上看,FastCGI 模式支援分散式運算。FastCGI 程式和宿主的 Server 完全獨立,FastCGI 程式掛了也不影響 Server;
  3. 從效能上看,FastCGI 模式把動態邏輯的處理從 Server 中分離出來,大負荷的 I O處理還是留給宿主 Server,這樣宿主 Server 可以一心一意處理 IO,對於一個普通的動態網頁來說, 邏輯處理可能只有一小部分,大量的是圖片等靜態。

  FastCGI 模式是目前 PHP 主流的 WEB 服務執行模式,擁有高效可靠的效能,推薦大家使用。

 Module 模式

  PHP 常常與 Apache 伺服器搭配形成 LAMP 配套的執行環境。把 PHP 作為一個子模組整合到 Apache 中,就是 Module 模式,Apache 中的常見配置如下:

LoadModule php5_module modules/mod_php5.so

  這使用了 LoadModule 命令,該命令的第一個引數是模組的名稱,名稱可以在模組實現的原始碼中找到。第二個選項是該模組所處的路徑。如果需要在伺服器執行時載入模組,可以通過傳送訊號 HUP 或者 AP_SIG_GRACEFUL 給伺服器,一旦接受到該訊號,Apache 將重新裝載模組,而不需要重新啟動伺服器。通過註冊到 apache2 的 ap_hook_post_config 掛鉤,在 Apache 啟動的時候啟動此模組以接受 PHP 檔案的請求。

  例如,當客戶端訪問 PHP 檔案時,Apache 就會呼叫 php5_module 來解析 PHP 指令碼。Apache 每接收到一個請求,都會產生一個程式來連線 PHP 完成請求。在 Module 模式下,有時候會因為把 PHP 作為模組編進 Apache,而導致出現問題時很難定位是 PHP 的問題還是 Apache 的問題。

過去,憑藉著豐富的模組和功能,企業往往將 Apache 作為 WEB 伺服器,於是以 Module 模式執行的 PHP + Apache 的組合很常見。近些年,以非同步事件驅動、高效能的 Nginx 伺服器的崛起,市場份額快速增長,以 FastCGI 模式執行的 PHP + Nginx 組合,擁有更佳的效能,有趕超 Apache 的趨勢。

 ISAPI 模式

  ISAPI(Internet Server Application Program Interface)是微軟提供的一套面向 Internet 服務的 API 介面,一個 ISAPI 的 DLL,可以在被使用者請求啟用後長駐記憶體,等待使用者的另一個請求,還可以在一個 DL L裡設定多個使用者請求處理函式,此外,ISAPI 的 DLL 應用程式和 WEB 伺服器處於同一個程式中,效率要顯著高於CGI。由於微軟的排他性,只能執行於 Windows 環境。

  用的比較少,在這裡就不做詳細介紹了。

相關文章