Web服務器與PHP應用的工作機制

聲明:
本文是對網上已有資料的整理,方便共同學習,文中附有相關鏈接供詳細查閱。

今天一起了解一下,Web 服務器與 PHP應用之間是如何工作的。
首先我們先來了解一下幾個概念及其之間的關係:Web服務器(Nginx)、CGI、FastCGI、PHP-CGI、PHP-FPM

Web服務器(Nginx)

Web服務器 通常指網站服務器,是指駐留於因特網上某種類型計算機的程序,主要功能是提供網上信息的瀏覽、下載等服務。
目前最主流的三個Web服務器是Apache、Nginx、 IIS。

Nginx:
Nginx 是一款自由、開源、小巧且高性能的 HTTP服務器 和 反向代碼裏服務器,同時它也是 IMAP / POP3 / SMTP 代理服務器。
Web Server(Nginx)只是內容的分發者。
服務器在收到客戶端發來的請求時

  • 如果請求的是靜態頁面或者圖片等無需動態處理的資源時,則Web服務器會根據請求的URL等信息去文件系統中找到並返回給瀏覽器,此時無需PHP參與。
  • 如果收到的是動態的頁面請求,這個時候Nginx就需要與PHP通信,就會用到CGI協議,將請求數據轉換成PHP能理解的信息,然後PHP根據這些信息返回進行相應的處理,處理完後,需要返回的信息也要通過CGI協議轉換成Nginx可以理解的信息,最後由Nginx將這些信息返回給客戶端。

CGI

CGI(Common Gateway Interface)全稱是 通用網關接口。CGI 協議同 HTTP 協議一樣是一個「應用層」協議,它的是爲了解決 Web 服務器與後臺語言之間的通信問題。

CGI 的運行原理

  • 當用戶訪問我們的 Web 應用時,會發起一個 HTTP 請求。最終 Web 服務器接收到這個請求。
  • Web 服務器創建一個新的 CGI 進程。在這個進程中,將 HTTP 請求數據已一定格式解析出來,並通過標準輸入和環境變量傳入到 URL 指定的 CGI 程序(PHP 應用 $_SERVER)。
  • Web 應用程序處理完成後將返回數據寫入到標準輸出中,Web 服務器進程則從標準輸出流中讀取到響應,並採用 HTTP 協議返回給用戶響應。

FastCGI

CGI協議每次處理用戶請求,都需要重新fork CGI子進程、銷燬CGI子進程,一系列的 I/O 開銷降低了網絡的吞吐量,造成了資源的浪費,在大併發時會產生嚴重的性能問題。隨着Web的興起,高併發呈常態化,於是就有了FastCGI,即FastCGI是基於CGI協議的基礎上做了改進,它是一種常駐型的CGI協議,它採用進程間通信(IPC)來處理用戶的請求。

FastCGI 協議運行原理

  • FastCGI 進程管理器啓動時會創建一個 主(Master) 進程和多個 CGI 解釋器進程(Worker 進程),然後等待 Web 服務器的連接。
  • Web 服務器接收 HTTP 請求後,將 CGI 報文通過 套接字(UNIX 或 TCP Socket)進行通信,將環境變量和請求數據寫入標準輸入,轉發到 CGI 解釋器進程。
  • CGI 解釋器進程完成處理後將標準輸出和錯誤信息從同一連接返回給 Web 服務器。
  • CGI 解釋器進程等待下一個 HTTP 請求的到來。

PHP-FPM

要了解PHP-FPM,就得先說說PHP-CGI。
PHP-CGI就是PHP實現的自帶的FastCGI管理器。 雖然是php官方出品,但是這丫的卻一點也不給力,性能太差,而且也很麻煩不人性化,主要體現在:

  1. php-cgi變更php.ini配置後,需重啓php-cgi才能讓新的php-ini生效,不可以平滑重啓。
  2. 直接殺死php-cgi進程,php就不能運行了

於是就有人專門爲PHP搞出了PHP專用的FastCGI管理器,即PHP-FPM。
PHP-FPM 是對於 FastCGI 協議的具體實現,他負責管理一個進程池,來處理來自Web服務器的請求。
因爲PHP-CGI只是個CGI程序,他自己本身只能解析請求,返回結果,不會進程管理。所以就出現了一些能夠調度 php-cgi 進程的程序,比如說由lighthttpd分離出來的spawn-fcgi。同樣,PHP-FPM也是用於調度管理PHP解析器php-cgi的管理程序。
PHP-FPM通過生成新的子進程可以實現php.ini修改後的平滑重啓。

總結

一句話總結:
CGI 和 FastCGI 是一種協議和 HTTP 協議一樣位於應用層,與語言無關;PHP-FPM 是一種 FastCGI 協議的實現,能夠管理 FastCGI 進程

兩張圖總結:
請求靜態頁面模型
請求動態頁面模型

PHP-FPM 是如何工作的

PHP-FPM 進程管理器有兩種進程組成,一個 Master 進程和多個 Worker 進程。Master 進程負責監聽端口,接收來自 Web 服務器的請求,然後指派具體的 Worker 進程處理請求;worker 進程則一般有多個 (依據配置決定進程數),每個進程內部都嵌入了一個 PHP 解釋器,用來執行 PHP 代碼。

從 FPM 接收到請求,到處理完畢,其具體的流程如下:

  1. FPM 的 master 進程接收到請求
  2. master 進程根據配置指派特定的 worker 進程進行請求處理,如果沒有可用進程,返回錯誤,這也是我們配合 Nginx 遇到502錯誤比較多的原因。
  3. worker 進程處理請求,如果超時,返回504錯誤
  4. 請求處理結束,返回結果

Nginx發送請求給FPM

我們知道,Nginx 不僅僅是一個 Web 服務器,也是一個功能強大的 Proxy 服務器,除了進行 http 請求的代理,也可以進行許多其他協議請求的代理,包括本文與 fpm 相關的 fastcgi 協議。爲了能夠使 Nginx 理解 fastcgi 協議,Nginx 提供了 fastcgi 模塊來將 http 請求映射爲對應的 fastcgi 請求。

Nginx 的 fastcgi 模塊提供了 fastcgi_param 指令來主要處理這些映射關係。

除此之外,非常重要的就是 fastcgi_pass 指令了,這個指令用於指定 fpm 進程監聽的地址,Nginx 會把所有的 php 請求翻譯成 fastcgi 請求之後再發送到這個地址,下面一個簡單的可以工作的 Nginx 配置文件:
Nginx配置
在這個配置文件中,我們新建了一個虛擬主機,監聽在 80 端口,Web 根目錄爲 /home/rf/projects/wordpress。然後我們通過 location 指令,將所有的以 .php 結尾的請求都交給 fastcgi 模塊處理,從而把所有的 php 請求都交給了 fpm 處理,從而完成 Nginx 到 fpm 的閉環。

再附兩張圖:
Nginx配置解釋
處理HTTP請求的流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章