這裏所說的 PHP 運行模式, 其實指的是 SAPI (Server Application Programming Interface,服務端應用編程端口 )。SAPI 爲 PHP 提供了一個和外部通訊的接口, PHP 就是經過這個接口來與其它的應用進行數據交互的。針對不一樣的應用場景, PHP 也提供了多種不一樣的 SAPI ,常見的有:apache、apache2filter、apache2handler、cli、cgi、embed 、fast-cgi、isapi 等等。 php
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 庫中。html
接下來會對其中五個比較常見的運行模式進行說明。web
CLI( Command Line Interface ), 也就是命令行接口,PHP 默認會安裝。經過這個接口,能夠在 shell 環境下與 PHP 進行交互 。在終端裏輸入 php -v
,會獲得相似下圖的結果(安裝了 PHP 前提下):shell
由於有 CLI 的存在,咱們能夠直接在終端命令行裏運行 PHP 腳本,就像使用 shell、Python 那樣,不用依賴於 WEB 服務器。好比 Laravel 框架中的 Artisan 命令行工具,它其實就是一個 PHP 腳本,用來幫助咱們快速構建 Laravel 應用的。apache
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 性能低下的主要緣由。segmentfault
CGI 模式的好處就是徹底獨立於任何服務器,僅僅是作爲一箇中介:提供接口給 WEB 服務器和腳本語言或者是徹底獨立編程語言。它們經過 CGI 協議搭線來完成數據傳遞。這樣作的好處了儘可能減小它們之間的關聯,使得各自更加獨立、互不影響。api
CGI 模式已是比較古老的模式了,這幾年都不多用了。瀏覽器
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 模式是目前 PHP 主流的 WEB 服務運行模式,擁有高效可靠的性能,推薦你們使用。
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(Internet Server Application Program Interface)是微軟提供的一套面向 Internet 服務的 API 接口,一個 ISAPI 的 DLL,能夠在被用戶請求激活後長駐內存,等待用戶的另外一個請求,還能夠在一個 DLL 裏設置多個用戶請求處理函數,此外,ISAPI 的 DLL 應用程序和 WEB 服務器處於同一個進程中,效率要顯著高於 CGI。因爲微軟的排他性,只能運行於 Windows 環境。
用的比較少,在這裏就不作詳細介紹了。
以上內容整理自網絡,參考文章: