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 模式的優點:
- 從穩定性上看,FastCGI 模式是以獨立的進程池來運行 CGI 協議程序,單獨一個進程死掉,系統可以很輕易的丟棄,然後重新分配新的進程來運行邏輯;
- 從安全性上看,FastCGI 模式支持分佈式運算。FastCGI 程序和宿主的 Server 完全獨立,FastCGI 程序掛了也不影響 Server;
- 從性能上看,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 環境。
閱讀更多 樂購IT教育學院 的文章