PHP-FPM 與 Nginx 的通信機制總結

2022-01-04 SegmentFault思否
PHP-FPM 介紹CGI 協議與 FastCGI 協議

每種動態語言( PHP、Python 等)的代碼文件需要通過對應的解析器才能被伺服器識別,而 CGI 協議就是用來使解釋器與伺服器可以互相通信。PHP 文件在伺服器上的解析需要用到 PHP 解釋器,再加上對應的 CGI 協議,從而使伺服器可以解析到 PHP 文件。

由於 CGI 的機制是每處理一個請求需要 fork 一個 CGI 進程,請求結束再 kill 掉這個進程,在實際應用上比較浪費資源,於是就出現了CGI 的改良版本 FastCGI,FastCGI 在請求處理完後,不會 kill 掉進程,而是繼續處理多個請求,這樣就大大提高了效率。

PHP-FPM 是什麼

PHP-FPM 即 PHP-FastCGI Process Manager, 它是 FastCGI 的實現,並提供了進程管理的功能。進程包含 master 進程和 worker 進程兩種;master 進程只有一個,負責監聽埠,接收來自伺服器的請求,而 worker 進程則一般有多個(具體數量根據實際需要進行配置),每個進程內部都會嵌入一個 PHP 解釋器,是代碼真正執行的地方。

Nginx 與 php-fpm 通信機制

當我們訪問一個網站(如 www.test.com)的時候,處理流程是這樣的:

www.test.com

|

|

Nginx

|

|

路由到 www.test.com/index.php

|

|

加載 nginx 的 fast-cgi 模塊

|

|

fast-cgi 監聽 127.0.0.1:9000 地址

|

|

www.test.com/index.php 請求到達 127.0.0.1:9000

|

|

等待處理...

Nginx 與 php-fpm 的結合

在 Linux 上,nginx 與 php-fpm 的通信有 tcp socket 和 unix socket 兩種方式。

tcp socket 的優點是可以跨伺服器,當 nginx 和 php-fpm 不在同一臺機器上時,只能使用這種方式。

Unix socket 又叫 IPC(inter-process communication 進程間通信) socket,用於實現同一主機上的進程間通信,這種方式需要在 nginx配置文件中填寫 php-fpm 的 socket 文件位置。

兩種方式的數據傳輸過程如下圖所示:

二者的不同:

由於 Unix socket 不需要經過網絡協議棧,不需要打包拆包、計算校驗和、維護序號和應答等,只是將應用層數據從一個進程拷貝到另一個進程。所以其效率比 tcp socket 的方式要高,可減少不必要的 tcp 開銷。不過,unix socket 高並發時不穩定,連接數爆發時,會產生大量的長時緩存,在沒有面向連接協議的支撐下,大數據包可能會直接出錯不返回異常。而 tcp 這樣的面向連接的協議,可以更好的保證通信的正確性和完整性。

Nginx 與 php-fpm 結合只需要在各自的配置文件中做設置即可:

1、Nginx 中的配置

以 tcp socket通信為例:

server {

listen 80; #監聽 80 埠,接收http請求

server_name www.test.com; #就是網站地址

root /usr/local/etc/nginx/www/huxintong_admin; # 準備存放代碼工程的路徑

#路由到網站根目錄 www.test.com 時候的處理

location / {

index index.php; #跳轉到 www.test.com/index.php

autoindex on;

}

#當請求網站下 php 文件的時候,反向代理到 php-fpm

location ~ \.php$ {

include /usr/local/etc/nginx/fastcgi.conf; #加載 nginx 的 fastcgi 模塊

fastcgi_intercept_errors on;

fastcgi_pass 127.0.0.1:9000; # tcp 方式,php-fpm 監聽的 IP 地址和埠

# fasrcgi_pass /usr/run/php-fpm.sock # unix socket 連接方式

}

}

2、php-fpm 的配置

listen = 127.0.0.1:9000

# 或者下面這樣

listen = /var/run/php-fpm.sock

注意,在使用 unix socket 方式連接時,由於 socket 文件本質上是一個文件,存在權限控制的問題,所以需要注意 nginx。

進程的權限與 php-fpm 的權限問題,不然會提示無權限訪問(在各自的配置文件裡設置用戶)。

通過以上配置即可完成 php-fpm 與 nginx 的通信。

在應用中的選擇

如果是在同一臺伺服器上運行的 nginx 和 php-fpm,且並發量不高(不超過1000),選擇unix socket,以提高 nginx 和 php-fpm 的通信效率。如果是面臨高並發業務,則考慮選擇使用更可靠的 tcp socket,以負載均衡、內核優化等運維手段維持效率。

若並發較高但仍想用 unix socket 時,可通過以下方式提高 unix socket 的穩定性。

1、將sock文件放在 /dev/shm 目錄下,此目錄下將 sock 文件放在內存裡面,內存的讀寫更快。

2、提高 backlog

backlog 默認位 128,1024 這個值換成自己正常的 QPS,配置如下。

nginx.conf 文件中:

server {

listen 80 default backlog = 1024;

}

php-fpm.conf 文件中:

listen.backlog = 1024

3、增加 sock 文件和 php-fpm 實例

在 /dev/shm 新建一個 sock 文件,在 nginx 中通過 upstream 模塊將請求負載均衡到兩個 sock 文件,並且將兩個 sock 文件分別對應到兩套 php-fpm 實例上。

歡迎關注 SegmentFault 微信公眾號 :)

相關焦點

  • 全面剖析 PHP-FPM+Nginx 通信原理
    fastcgi_pass unix:/tmp/php-cgi.sock;它其實是Nginx和PHP-FPM一個通信載體(或者說通信方式),目的是為了讓Nginx知道,收到動態請求之後該往哪兒發。php-fpm和nginx一樣,也會監聽埠(通過nginx.conf裡的配置我們知道,nginx默認監聽8080埠,php-fpm默認監聽9000埠),並且有master和worker進程,worker負責處理每一個php請求關於fastcgi:fastcgi是一個協議。市面上有多種實現了fastcgi協議的進程管理器,php-fpm就是其中的一種。
  • nginx和php-fpm通信,使用unix socket還是TCP?
    兩種方式各有優缺點,這裡先給出兩種的配置方法,然後再對性能、安全性等做出總結。fastcgi_index index.php; include fastcgi_params; }第二步,編輯php-fpm配置文件 /etc/php5/fpm/pool.d/www.conf將listen參數修改為127.0.0.1:9000,像這樣:第三步,重啟php-fpm,重啟nginx二
  • nginx調用php-fpm的工作原理
    5、當需要處理php請求時,nginx的worker進程會將請求移交給php-fpm的worker進程進行處理,也就是最開頭所說的nginx調用了php,其實嚴格得講是nginx間接調用php。了解了上面的這五個簡單原理,在nginx中配置php調用方法就變得易如反掌。
  • Nginx+Php-fpm運行原理詳解
    Php-fpm是什麼1、cgi、fast-cgi協議cgi的歷史早期的webserver只處理html等靜態文件,但是隨著技術的發展,出現了像php等動態語言。webserver處理不了了,怎麼辦呢?那就交給php解釋器來處理吧!交給php解釋器處理很好,但是,php解釋器如何與webserver進行通信呢?
  • php-fpm詳解
    對於php.ini文件的修改,php-cgi進程是沒辦法平滑重啟的,有了php-fpm後,就把平滑重啟成為了一種可能,php-fpm對此的處理機制是新的worker用新的配置,已經存在的worker處理完手上的活就可以歇著了,通過這種機制來平滑過度的。
  • PHP - FPM 應用淺析
    fpm可以同時監聽多個埠,每個埠對應一個worker pool,而每個pool下對應多個worker進程,類似nginx中server概念。由於php-fpm是短連接的,所以每次請求都會先建立連接,建立連接的過程必然會觸發上圖的執行步驟,所以,在大流量的系統上master進程會變得繁忙, 佔用系統cpu資源,不適合大流量環境的部署。配置總結:內存比較少,並發量不是很大的應用,可以考慮採用 dynamic 的方式,這樣可以控制 php-fpm 所消耗的總內存數。
  • ubuntu中安裝和配置nginx+php-fpm
    發行版已經很貼心的把這些常用的工具都放在軟體倉庫裡了,這裡以ubuntu為例:sudo apt-get install nginxsudo apt-get install php-fpm php-gd php-mbstring php-mysql第一句就是安裝nginx,第二句就是安裝php-fpm和常用的組件。
  • (實用篇)PHP-FPM配置及使用總結
    這個時長配置可以在php.ini(max_execution_time)或php-fpm.conf中配置均可,為了不影響全局配置,可在php-fpm.conf中實現。值得注意的是:需要結合nginx.conf中的max_fail(調大些)和fail_timeout(調小些)一同配置。
  • php環境搭建(正確配置nginx和php)
    即nginx可以作為一個HTTP伺服器進行網站的發布處理,也可以作為一個反向代理伺服器進行負載均衡。但需要注意的是:nginx本身並不會對php文件進行解析。對PHP頁面的請求將會被nginx交給FastCGI進程監聽的IP位址及埠,由php-fpm(第三方的fastcgi進程管理器)作為動態解析伺服器處理,最後將處理結果再返回給nginx。
  • 502錯誤,讓你進一步明白nginx和php-fpm之間的關係
    (1)nginx.conf:error_log  logs/error.log;user www-data www-data;(2)php-fpm.conf:access.log = /var/log/fpm.log(3)pool.d/www.conf(PHP-FPM pool 配置文件):user
  • PHP 連接方式介紹以及如何攻擊 PHP-FPM
    ,第三張圖的 FPM 代表了 php-fpm 進程的 fastcgi 模式一般來說,apache 伺服器常用 module 方式起 php,nginx 伺服器常用 fastcgi 模式起 php,所以接下來我已 nginx 為例php-fpm 的模式是不是很繞,php-fpm 下還可以繼續分,如果使用 fastcgi 模式,nginx 與 php-fpm 通信可以通過兩種模式
  • php-fpm優化
    ];pid = /var/log/php-fpm/php-fpm.pid #pid文件存放的位置;error_log = /var/log/php-fpm/php-fpm.log #錯誤日誌存放的位置;log_level = error #日誌級別, alert, error, warning, notice, debugrlimit_files = 65535 #php-fpm
  • php-fpm rce攻擊
    apache 也可以設置為 php-fpm 方式mod_php 通過嵌入 PHP 解釋器到 apache 進程中,只能與 apache 配合使用而 cgi 和 fast-cgi 以獨立的進程的形式出現,只要對應的Web伺服器實現 cgi 或者 fast-cgi 協議,就能夠處理 PHP 請求0x01 PHP-FPM 的模式nginx 與 php-fpm 通信可以通過兩種模式
  • 為多個PHP-FPM容器量身打造單一Nginx鏡像
    如果你只服務一個PHP-FPM容器應用,在你的Nginx容器的配置文件中硬編碼對應的名字是可以的。基礎鏡像版本陳舊,兩年多沒更新了。現在,如果你想運行一個伴隨著nginx容器的動態命名後端應用,你只需要簡單地這麼做:shell# Pull down the latest from Docker Hubdocker pull shiphp/nginx-env:latest# Run a PHP container named "php-fpm-api"docker run --name php-fpm-api
  • 只需某些特定的Nginx + PHP-FPM 配置,即可觸發PHP 遠程代碼執行漏洞
    他和另外兩名研究員 Emil Lerner 和 beched 研究發現,在某些 nginx +php-fpm 配置下,漏洞即可被觸發。如果一臺 web 伺服器運行 nginx +php-fpm且 nginx 的配置如下:location ~ [^/]\.php(/|$) { ... fastcgi_split_path_info ^(.+?
  • FastCgi與PHP-fpm之間的關係
    web server(比如說nginx)只是內容的分發者。比如,如果請求/index.html,那麼web server會去文件系統中找到這個文件,發送給瀏覽器,這裡分發的是靜態數據。好了,如果現在請求的是/index.php,根據配置文件,nginx 知道這個不是靜態文件,需要去找PHP解析器來處理,那麼他會把這個請求簡單處理後交給PHP解析器。
  • 如何在 CentOS 7 中使用 Nginx 和 PHP7-FPM 安裝 Nextcloud
    php -v查看 PHP 版本號步驟 2 - 配置 PHP7-FPM在這一個步驟中,我們將配置 php-fpm 與 Nginx 協同運行。Php7-fpm 將使用 nginx 用戶來運行,並監聽 9000 埠。使用 vim 編輯默認的 php7-fpm 配置文件。
  • 如何利用PHP-FPM實現open_basedir繞過
    TCP通信模式允許通過網絡進程之間的通信,也可以通過loopback進行本地進程之間通信。ondrej/php sudo apt update sudo apt install -y php7.3-fpm修改nginx站點文件sudo vim /etc/nginx/sites-enabled
  • 漏洞警告:PHP 官方披露了Nginx + php-fpm 部分配置下存在的遠程代碼執行高危漏洞
    官方發布了在 Nginx 配置不當的情況下 php-fpm 可導致遠程代碼執行的漏洞。但由於是配置文件的開放性,還請使用nginx+php-fpm 的服務管理員/運維人員及時做好自查自檢工作。【漏洞詳情】        PHP 官方發布漏洞通告,提到 Nginx 與 php-fpm 伺服器上存在的一處高危漏洞,由於Nginx的 fastcgi_split_path_info 模塊在處理帶 %0a 的請求時,對換行符 \n 處置不慎導致將 PATH_INFO 置為空,從而導致 php-fpm 組件在處理
  • 用 caddy 代替 nginx, 一行配置搞定 php-fpm 反向代理
    一是當時 nginx 還是非常堅挺, 可以說在 nginx + php-fpm 這一搭配方面, 基本上無敵手. 二是, 當時我試用過 Caddyfile 後,發現它太簡潔了,簡潔到我以配置 nginx 的思維, 完全無法適應配置 Caddyfile. 沒錯, 我當時覺得 , 配置 nginx 比 Caddyfile 簡單多了 (因為 nginx 配置已經熟練多年).