網絡上有不少關於如何配置 Nginx + FPM 的文章,但它們更多從操做的角度出發,告訴咱們怎麼作,但卻沒有告訴咱們爲何要這麼作,本文從 Nginx 與 FPM 的工做機制出發,探討配置背後的原理,讓咱們真正理解 Nginx 與 PHP 是如何協同工做的。要說 Nginx 與 PHP 是如何協同工做的,首先得說 CGI (Common Gateway Interface) 和 FastCGI 這兩個協議。php
CGI 是 Web Server 與後臺語言交互的協議,有了這個協議,開發者可使用任何語言處理 Web Server 發來的請求,動態的生成內容。但 CGI 有一個致命的缺點,那就是每處理一個請求都須要 fork 一個全新的進程,隨着 Web 的興起,高併發愈來愈成爲常態,這樣低效的方式明顯不能知足需求。就這樣,FastCGI 誕生了,CGI 很快就退出了歷史的舞臺。FastCGI,顧名思義爲更快的 CGI,它容許在一個進程內處理多個請求,而不是一個請求處理完畢就直接結束進程,性能上有了很大的提升。服務器
至於 FPM (FastCGI Process Manager),它是 FastCGI 的實現,任何實現了 FastCGI 協議的 Web Server 都可以與之通訊。FPM 之於標準的 FastCGI,也提供了一些加強功能,具體能夠參考官方文檔:PHP: FPM Installation。網絡
FPM 是一個 PHP 進程管理器,包含 master 進程和 worker 進程兩種進程:master 進程只有一個,負責監聽端口,接收來自 Web Server 的請求,而 worker 進程則通常有多個 (具體數量根據實際須要配置),每一個進程內部都嵌入了一個 PHP 解釋器,是 PHP 代碼真正執行的地方,下圖是我本機上 fpm 的進程狀況,1一個 master 進程,3個 worker 進程:併發
從 FPM 接收到請求,處處理完畢,其具體的流程以下:wordpress
FPM 的 master 進程接收到請求高併發
master 進程根據配置指派特定的 worker 進程進行請求處理,若是沒有可用進程,返回錯誤,這也是咱們配合 Nginx 遇到502錯誤比較多的緣由。性能
worker 進程處理請求,若是超時,返回504錯誤翻譯
請求處理結束,返回結果代理
FPM 從接收處處理請求的流程就是這樣了,那麼 Nginx 又是如何發送請求給 fpm 的呢?這就須要從 Nginx 層面來講明瞭。blog
咱們知道,Nginx 不單單是一個 Web 服務器,也是一個功能強大的 Proxy 服務器,除了進行 http 請求的代理,也能夠進行許多其餘協議請求的代理,包括本文與 fpm 相關的 fastcgi 協議。爲了可以使 Nginx 理解 fastcgi 協議,Nginx 提供了 fastcgi 模塊來將 http 請求映射爲對應的 fastcgi 請求。
Nginx 的 fastcgi 模塊提供了 fastcgi_param 指令來主要處理這些映射關係,下面 Ubuntu 下 Nginx 的一個配置文件,其主要完成的工做是將 Nginx 中的變量翻譯成 PHP 中可以理解的變量。
除此以外,很是重要的就是 fastcgi_pass 指令了,這個指令用於指定 fpm 進程監聽的地址,Nginx 會把全部的 php 請求翻譯成 fastcgi 請求以後再發送到這個地址。下面一個簡單的能夠工做的 Nginx 配置文件:
在這個配置文件中,咱們新建了一個虛擬主機,監聽在 80 端口,Web 根目錄爲 /home/rf/projects/wordpress。而後咱們經過 location 指令,將全部的以 .php 結尾的請求都交給 fastcgi 模塊處理,從而把全部的 php 請求都交給了 fpm 處理,從而完成 Nginx 到 fpm 的閉環。
如此以來,Nginx 與 FPM 通訊的整個流程應該比較清晰了吧。