nginx+php-fpm工做原理

官方解釋php-fpm

官方手冊:FPM(FastCGI 進程管理器)用於替換 PHP FastCGI 的大部分附加功能,對於高負載網站是很是有用的。
它的功能包括:php

  • 支持平滑中止/啓動的高級進程管理功能;
  • 能夠工做於不一樣的 uid/gid/chroot 環境下,並監聽不一樣的端口和使用不一樣的 php.ini 配置文件(可取代 safe_mode 的設置);
  • stdout 和 stderr 日誌記錄;
  • 在發生意外狀況的時候可以從新啓動並緩存被破壞的 opcode;
  • 文件上傳優化支持;
  • "慢日誌" - 記錄腳本(不只記錄文件名,還記錄 PHP backtrace 信息,可使用 ptrace或者相似工具讀取和分析遠程進程的運行數據)運行所致使的異常緩慢;
  • fastcgi_finish_request() - 特殊功能:用於在請求完成和刷新數據後,繼續在後臺執行耗時的工做(錄入視頻轉換、統計處理等);
  • 動態/靜態子進程產生;
  • 基本 SAPI 運行狀態信息(相似Apache的 mod_status);
  • 基於 php.ini 的配置文件。

從官方手冊來看,php-fpm是一個FastCGI的進程管理器,用來管理FastCGI進程的。
那麼什麼是FastCGI呢?這個咱們要從CGI提及。html

CGI

CGI (Common Gateway Interface)是 Web Server 與後臺語言交互的協議,有了這個協議,開發者可使用任何語言處理 Web Server 發來的請求,動態的生成內容。保證了傳遞過來的數據是標準格式的(規定了以什麼樣的格式傳哪些數據(URL、查詢字符串、POST數據、HTTP header等等)),方便了開發者。nginx

PHP-CGI

PHP語言對應與服務器交互的CGI程序就是PHP-CGI。
CGI程序自己只能解析請求、返回結果,不會進程管理,因此有一個致命的缺點,那就是每處理一個請求都須要fork一個全新的進程,隨着Web的興起,高併發愈來愈成爲常態,這樣低效的方式明顯不能知足需求(每一次web請求都會有啓動和退出進程,也就是最爲人詬病的fork-and-execute模式,這樣一在大規模併發下,就死翹翹了)。就這樣,FastCGI誕生了,CGI程序很快就退出了歷史的舞臺。web

FastCGI

FastCGI,顧名思義爲更快的 CGI,它容許在一個進程內處理多個請求,而不是一個請求處理完畢就直接結束進程,性能上有了很大的提升。FastCGI也能夠說是一種協議segmentfault

  • 那麼FastCGI是怎麼作的呢?

首先,FastCGI會先啓一個master進程,解析配置文件,初始化執行環境,而後再啓動多個worker進程。當請求過來時,master會傳遞給一個worker,而後當即能夠接受下一個請求。
這樣就避免了重複的勞動,效率天然是高。
並且當worker不夠用時,master能夠根據配置預先啓動幾個worker等着。
固然空閒worker太多時,也會停掉一些,這樣就提升了性能,也節約了資源。這就是FastCGI的對進程的管理。瀏覽器

那如今咱們能夠大體上想象到php-fpm是個什麼東東了吧!緩存

PHP-FPM

FPM 是一個 PHP 進程管理器,包含 master 進程和 worker 進程兩種進程:master 進程只有一個,負責監聽端口,接收來自 Web Server 的請求,而 worker 進程則通常有多個 (具體數量根據實際須要配置),每一個進程內部都嵌入了一個 PHP 解釋器,是 PHP 代碼真正執行的地方,下面是我本機上FPM的進程狀況:1個master進程,2個worker進程。bash

圖1.png

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

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

FPM從接收處處理請求的流程就是這樣了,那麼Nginx又是如何發送請求給FPM的呢?併發

Nginx

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

Nginx的FastCGI模塊提供了fastcgi_param指令來主要處理這些映射關係,下面 是Nginx的一個配置文件實例,其主要完成的工做是將Nginx中的變量翻譯成PHP中可以理解的變量。
圖2.png

除此以外,很是重要的就是fastcgi_pass指令了,這個指令用於指定FPM進程監聽的地址,Nginx會把全部的PHP請求翻譯成FastCGI請求以後再發送到這個地址。下面一個簡單的能夠工做的Nginx配置文件:

server {
    listen 80;
    server_name www.example.com;
    root /usr/local/web/Mr_J/public;
    index index.php index.html index.htm;

    access_log /usr/local/nginx/logs/test-access.log;
    error_log  /usr/local/nginx/logs/test-error.log;

    location / {
      try_files $uri $uri/ /index.php?$query_string;
    }

    location ~\.php$ {
          fastcgi_pass   127.0.0.1;
          fastcgi_index  index.php;
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
          include        fastcgi_params;
    }
}

在這個配置文件中,咱們新建了一個虛擬主機,監聽80端口,項目根目錄爲 /usr/local/web/Mr_J/public。而後咱們經過location指令,將全部的以.php結尾的請求都交給FastCGI模塊處理,從而把全部的PHP請求都交給了FPM處理,從而完成Nginx到FPM的閉環。
如此以來,Nginx與FPM通訊的整個流程應該比較清晰了。

www.example.com
        |
        |
      Nginx
        |
        |
路由到www.example.com/index.php
        |
        |
加載nginx的fast-cgi模塊
        |
        |
fast-cgi監聽127.0.0.1:9000地址
        |
        |
www.example.com/index.php請求到達127.0.0.1:9000
        |
        |
php-fpm 監聽127.0.0.1:9000
        |
        |
php-fpm 接收到請求,啓用worker進程處理請求
        |
        |
php-fpm 處理完請求,返回給nginx
        |
        |
nginx將結果經過http返回給瀏覽器

參考資料

Nginx+Php-fpm運行原理詳解
理解 Nginx 與 PHP-FPM 通訊的工做機制
CGI、FastCGI和PHP-FPM關係圖解

相關文章
相關標籤/搜索