ホームページ  >  記事  >  運用・保守  >  Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

青灯夜游
青灯夜游転載
2022-03-11 11:11:434448ブラウズ

この記事では、Nginx と php-fpm の間の通信メカニズムについて説明します。

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

CGI とは何ですか?

Fastcgi について話す前に、まず CGI について話す必要があります。CGI は、 Web サーバーによって渡されるデータは、標準形式ではプロトコルです。各動的言語 (PHP、Python など) のコード ファイルは、サーバーに認識されるように対応するパーサーを通過する必要があり、インタプリタとサーバーが相互に通信できるようにするために CGI プロトコルが使用されます。サーバー上の PHP ファイルを解析するには、サーバーが PHP ファイルを解析できるように、PHP インタープリターを対応する CGI プロトコルと組み合わせて使用​​する必要があります。

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

1. ユーザーはクライアント (ブラウザ) を通じて www などの URL を入力します。 .baidu.com。

2. ブラウザは一連の処理を経て(ここでは処理は省略します)、対応するサーバーにリクエストを送信します。

3. サーバー ネットワーク カードは、監視対象ポートに基づいて、対応するソフトウェア サービスにリクエストを送信します。

4. Web サーバー (Nginx/Apache などの Web ソフトウェア) がリクエストを受信すると、fast-cgi または cgi プロトコルを通じてリクエスト データを php-fpm プロセス マネージャーに転送します。 php-fpm は以下のアイドル状態のワークプロセスにタスクを送信しますが、このときワークプロセス内の php インタプリタがファイルの処理を開始します。

5. PHP インタープリターがそれを処理し、変換されたデータを fast-cgi または cgi プロトコルを通じて Web サーバーに返し、Web サーバーがクライアントに応答します。

FastCGI とは何ですか?

Fastcgi は CGI のより高度な方法であり、CGI プログラムのパフォーマンスを向上させるために使用されます。 CGI メカニズムでは各リクエストを処理する必要があるため、CGI プロセスをフォークし、リクエストが完了した後にプロセスを強制終了する必要があり、実際のアプリケーションではリソースの無駄になります。リクエストが処理された後、FastCGI はプロセスを Kill せずに複数のリクエストを処理し続けるため、効率が大幅に向上します。

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

php-fpm とは何ですか?

PHP-FPM は、FastCGI を実装し、プロセス管理機能を提供する PHP-FastCGI Process Manager です。プロセスには、マスター プロセスとワーカー プロセスの 2 つのタイプが含まれます。マスター プロセスは 1 つだけあり、ポートをリッスンしてサーバーからリクエストを受信する役割を果たしますが、通常は複数のワーカー プロセスが存在します (特定の数は実際のプロセスに応じて構成されます)。 PHP インタープリターは、コードが実際に実行される場所です。 php-fpm が登場する前は、php.ini の構成情報を変更するたびに、次の問題に直面していました。

  • 構成を有効にするには、php-cgi プログラムを再起動する必要があります。ファイルは有効になり、php-cgi はスムーズな再起動をサポートしません。

  • php-cgi プログラムを強制終了する場合は、再起動する必要があります。再起動しないと、PHP が正しく動作しません。

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

したがって、php-fpm は次のように理解できます。 Fastcgi プロトコルを実装し、Fastcgi によって開始されるプロセス、つまり php-cgi プロセスをスケジュールできるプログラムを管理するために使用されます。 PHP-FPM は PHP カーネルに統合されました。 --enalbe-fpm コンパイル パラメーターを使用するだけです。また、php.ini 設定ファイルを変更した後はスムーズに再起動できず、php-fpm を再起動する必要があります。現時点では、新しいフォークのワーカーは新しい構成を使用し、既存のワーカーは引き続き現在の作業を完了します。

Web服务器与程序解析器运行流程(Nginx与php-fpm通信机制(通信流程))

web server(如nginx)只是内容的分发者。比如,如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态资源。如果现在请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器。此时CGI便是规定了要传什么数据/以什么格式传输给php解析器的协议。当web server收到/index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以CGI规定的格式返回处理后的结果,退出进程。

CGI与FastCGI相比较

两者的主要差距在于性能瓶颈。前者接受到一个请求就会fork一个进程,后者则是事先启动一部分的worker进程。

CGI工作原理

CGI针对每个http请求都是fork一个新进程来进行处理,接着读取php.ini文件配置信息,初始化执行环境等。

2.然后这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户。

3.刚才fork的进程也随之退出。

4.如果下次用户还请求动态资源,那么web服务器又再次fork一个新进程,周而复始的进行。

FastCGI工作原理

Fastcgi则会先fork一个master,解析配置文件,初始化执行环境,然后再fork多个worker。

2.当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。

3.而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是Fastcgi的对进程的管理。大多数Fastcgi实现都会维护一个进程池。

注:swoole作为httpserver,实际上也是类似这样的工作方式。

Nginx与php-fpm通信分析

Nginx与php-fpm通信有两种方式,一种是通过tcp socket和 unix socket。前者是通过ip:端口方式进行通信,后者是通过php启动生成的socket文件进行通信。因此tcp socket的方式可以将两者分布再不同的机器上,只要Nginx能够连接到php服务器的端口即可。后者的方式,是统一主机上进行通讯的方式,因此两者只能再同一台机器上面。

tcp socket和 unix socket两者的优缺点

由于 Unix socket 不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。所以其效率比 tcp socket 的方式要高,可减少不必要的 tcp 开销。不过,unix socket 高并发时不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。而 tcp 这样的面向连接的协议,可以更好的保证通信的正确性和完整性。

如何选择tcp socket与unix socket

1.由于tcp方式相对unix的方式,并发量更高,因此针对并发量高的项目,建议采用tcp方式,现在Nginx配置示例文件默认的也是tcp方式。

2.使用unix方式,可以优化的点,就是将socket文件放在/dev/shm目录下面,至于为什么放在这个目录可以参考.https://www.linuxidc.com/Linux/2014-05/101818.htm。大致的意思,就是该目录下面的文件是不是存储再硬盘中的,而是存储再内存中的。至于硬盘读取和内存读取,谁快谁慢,肯定是内存最快了。

3.使用unix方式可以使用backlog,backlog的介绍,可以参考该文章。https://blog.csdn.net/raintungli/article/details/37913765。具体的配置可以参考下面。nginx 配置:

server {
  listen 80 default backlog = 100;
  }

php-fpm 配置:

listen.backlog = 1000
配置示例

Nginx与PHP通信的方式,取决于PHP启动的方式,下面直接演示两种方式的配置文件,后面记录PHP启动方式的配置 1.tcp socket

server {
        listen       80;
        server_name  laravel_demo.com;
        charset utf-8;
        access_log  logs/laravel_demo.com.access.log;
        root   /usr/local/var/www/laravel64_demo/public/;
        index  index.php index.html index.htm;

        error_page   500 502 503 504  /50x.html;

        location / {
            if (!-e $request_filename) {
                rewrite ^(.*)$  /index.php?s=$1 last;
                break;
            }
        }
        ### 此处就是Nginx与tcp socket通信配置,这里部署的同一台及其,因此IP就是127.0.0.1
        location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }
    }

2.unix socket

server {
        listen       80;
        server_name  laravel_demo.com;
        charset utf-8;
        access_log  logs/laravel_demo.com.access.log;
        root   /usr/local/var/www/laravel64_demo/public/;
        index  index.php index.html index.htm;

        error_page   500 502 503 504  /50x.html;

        location / {
            if (!-e $request_filename) {
                rewrite ^(.*)$  /index.php?s=$1 last;
                break;
            }
        }
        ### 此处就是Nginx与unix socket通信配置,我的socket文件在/usr/run/目录下
        location ~ \.php$ {
                fasrcgi_pass /usr/tmp/php-fpm.sock;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }
    }

上面演示了具体的配置示例,下面演示的是PHP启动方式的配置,这里需要和上面Nginx的配置一致,如果是tcp方式就采用tcp方式启动,如果是unix方式采用socket文件的方式启动。

# tcp方式启动
listen = 127.0.0.1:9000
# unix方式启动
listen = /usr/tmp/php-fpm.sock;

采用上面的两种方式中的任意一种,直接使用php-fpm方式启动php即可。

1、tcp方式启动的效果图

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

2、unix方式启动的效果图

Nginx と php-fpm 間の通信メカニズムを簡単に分析した記事

注意在演示的过程中遇到一个问题就是提示Nginx无法读取php生成的unix socket文件。这中情况是因为权限组导致的。因此再php-fpm的配置配置文件中要设置权限组,同时Nginx也需要设置权限组,再很多的集成开发环境中已经配置好了,因此可以减少此步骤。下面就是示例 Nginx配置文件:

#配置php-fpm的用户以及所属用户组
user  www www;

worker_processes auto;

error_log  /home/wwwlogs/nginx_error.log  crit;

pid        /usr/local/nginx/logs/nginx.pid;

#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 51200;

php-fpm配置文件(我们平常可能更多的是配置php.ini的文件,这里需要区分两者之间的区别,php.ini是针对php的配置文件,可以简单的理解为php再编译源码时会用到这里的配置,而关于php这个应用程序执行的情况就会用到php-fpm的配置文件):

; 配置php-fpm的用户以及所属用户组
user = www
group = www

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
;listen = 127.0.0.1:9000
listen = /usr/tmp/php-fpm.sock;

推荐教程:nginx教程

以上がNginx と php-fpm 間の通信メカニズムを簡単に分析した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcloud.tencent.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。