`

理解Nginx与PHP-FPM通信工作机制(非原创)

 
阅读更多

声明: 我这篇博客是手抄  理解 Nginx 与 PHP-FPM 通信的工作机制  ,目的是加强我的记忆。

 

还有一更详细的, 深入剖析 Web 服务器与 PHP 应用之间的通信机制 - 掌握 CGI 和 FastCGI 协议的运行原理

 

浏览器请求网页的过程

 请求静态页面

 

Borwser 请求 index.html -》 Web server (nginx/apache)分发,找到index.html 文件直接返回给Browser。

 

请求动态脚本

 

Browser 请求 index.php -》 Web server(nginx/apache)分发-》 php解析器(php-CGI 程序)-》返回处理结果给Web server -》 返回给 Browser。

 

原理是,服务器根据配置文件,知道这是一个脚本文件,然后需要去找php解析器来处理,php解析器会根据解析php.ini文件初始化执行环境,然后处理请求,再以标准的数据格式返回处理结果,最后退出进程。

 

CGI到FPM进化史  

 

CGI(Common Gateway Interface)

 

CGI是服务器与后台语言(php/python)交互的协议,有了这个协议,开发者可以使用任何语言来处理服务器转发过来的请求,动态地生成内容,保证了传递过来的数据是标准格式的,即规定了以什么样的格式传哪些数据,包括URL、查询字符串、POST数据、HTTP header等等,方便了开发者。

 

PHP-CGI

 

php语言对应与服务器交互的CGI程序就是PHP-CGI 。

 

CGI程序本身只能解析请求、返回结果,不会进程管理,所以有一个致命的缺点,那就是每处理一个请求都会fork一个全新的进程,随着web的兴起,高并发越来越成为常态,这样的方式显然不能满足需求,每一次web请求都会有启动和退出,也就是最为人们诟病的fork-and-execute模式,这样在大并发的情况下机器就死翘翘了。

 

于是,FastCGI诞生了,CGI程序很快退出历史舞台。

 

FastCGI

 

FastCGI,顾名思义就是更快的CGI程序,用来提高CGI程序性能,它允许在一个进程内处理多个请求,而不是一个请求处理完就直接结束进程,性能上有了很大的提高。

 

具体地,FastCGI是如何提高性能的呢?先看CGI程序的性能问题出在哪儿。

 

php解析器会解析php.ini文件,初始化执行环境,就是这里了。标准的CGI程序对每个请求都会执行这些步骤,所以每个请求的时间都会bijiaochang。

 

那么FastCGI是怎么做的呢?

 

首先,FastCGI会先启动一个master进程,解析php.ini配置文件,初始化执行环境,然后再启动多个worker进程。当有请求过来的时候,master会把请求传递给worker,然后立即可以处理下一个请求。这样避免了重复的劳动,效率自然提高了。

 

而且,当worker不够用时,master可以根据配置预先启动几个workder等着。当空闲的worker太多时,也会主动停掉一些,这样就提高了性能也节约了资源。这就是FastCGI对进程的管理。

 

补充: 也有一些能够调度PHP-CGI的程序,比如说说由lighthttpd分离出来的spawn-fcgi。当然,PHP-FPM也是这样的程序,在长期的发展后,逐渐得到了大家都认可,现在非常流行。

 

 

 

 

PHP-FPM(FastCGI Process Manager)

 

 它是FastCGI的一个实现,任何实现了FastCGI协议的服务器都可以与它进行通信。FPM之于标准的FastCGI,也提供了一些增强功能,具体可以参考官方文档:PHP: FPM Installation。 

 

FPM是一个PHP进程管理器,包含master和worker两种进程。

 

master进程只有一个,负责监听端口,接受来自服务器的请求,而worker进程则一般有多个(具体数量根据配置)。每个进程内部都嵌入一个PHP解释器,是PHP代码真正执行的地方,下面是我本机上FPM的进程情况,1个master进程,2个worker进程。

 

 

$ ps -ef | grep fpm
root       130     1  0 01:37 ?        00:00:01 php-fpm: master process (/usr/local/php/etc/php-fpm.conf)
php-fpm    131   130  0 01:37 ?        00:00:00 php-fpm: pool www
php-fpm    133   130  0 01:43 ?        00:00:00 php-fpm: pool www

 

 

 从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能理解的变量。

 

$ cat /usr/local/nginx/conf/fastcgi.conf

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

 

除此之外,就是fastcgi_pass指令了,这个指令用于指定FPM进程监听的地址,Nginx会把所有的PHP请求翻译成FastCGI请求之后发送到这个地址,下面是配置文件:

 

server {
    listen 80;
    server_name test.me;
    root /usr/local/web/myproject/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$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/local/web/myproject/public/$fastcgi_script_name;
        fastcgi_pass unix:/usr/local/php/var/run/php-fpm.sock;
        fastcgi_index index.php;
    }
}

 

 

上面这个配置文件中,我们新建立一个虚拟主机,监听80端口,项目跟目录指向/usr/local/web/myproject/public; 然后我们通过location指令将所有以.php结尾的请求都交给FastCGI模块处理,从而把所有的PHP请求都交给了FPM处理,从而完成Nginx到FPM的闭环。

如此以来,Nginx与FPM的通信流程就比较清晰了。

 

 

 

 

 

 

最后,修改了php.ini配置文件后。使用PHP-FPM为什么可以平滑重启呢?

 

修改了php.ini之后,PHP-CGI进程是没办法平滑重启的。PHP-FPM对此的处理机制是新的worker进程用新的配置,已经存在的worker进程处理完手上的活就可以歇着了,通过这汇总机制来平滑过渡。

 

 

 

 最后的最后,我写这个的最初原因是想知道Nginx跟PHP-FPM有哪几种通信方式。

 

这个问题的答案是:两种。分别是 unix socket和TCP socket。

 

 unix socket 配置如下:

 

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;

}

unix socket是一种终端,可以使同一台操作系统上两个或多个进程进行数据通信。这种方式需要在Nginx配置文件中填写PHP-FPM的pid文件位置,效率比TCP socket高。 

 

 

 TCP socket配置如下:

 

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

tcp socket的优点是可以跨服务器,如果Nginx和FPM不在一台机器上只能通过这种方式。 

 

 优缺点比较:

 

先看通信图解,如下:

 

 

 

 

 

 从这图中不难看出,unix socket 减少了不必要的TCP开销,TCP需要经过loopback,还要申请临时端口和TCP相关资源,但是 unix socket高并发时候并不稳定,连接数爆发时,会产生大量的长时缓存,在没有面向连接协议的支撑下,大数据包可能会直接出错不返回异常。TCP这样的面向连接的协议,多少可以保证通信的正确性和完整性。

 

建议: 如果是同一台机器上运行Nginx和FPM,并发量不超过1000,选择unix socket方式,这样可以避免一些检查操作、路由等。因此更快、更轻。 如果面临高并发业务,选择更可靠TCP socket,还可以做负载均衡,内核优化等运维手段提维持效率。

 

 

 最最最最后,既然说到web server和PHP的通信,顺便提一下我的新发现。 在我上一篇博文 keepalived+nginx高可用web架构实践  中我需要搭建一台web server,灵机一动决定用docker配置apache和PHP,分别下载两个镜像并启动容器,我需要关联两个容器。我找到一个配置,居然是apache通过FastCGI方式调用PHP的。因为以前配置apache+PHP都是直接加载PHP模块,配置如下:

 

LoadModule php7_module        modules/libphp7.so 


AddType application/x-httpd-php .php
<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule

 

FastCGI配置如下:

 

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

<VirtualHost *:80>
    DocumentRoot "/www/mysite.com"
    ServerName mysite.com
    ServerAlias www.mysite.com
   ProxyRequests Off
   ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/www/mysite.com/$1
    <Directory "/www/mysite.com">
        Options none
        AllowOverride none
        Require all granted
    </Directory>
</VirtualHost>

 

 

 

  • 大小: 125.5 KB
分享到:
评论

相关推荐

    理解 Nginx 与 PHP-FPM 通信的工作机制

    理解 Nginx 与 PHP-FPM 通信的工作机制

    php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式

    在这个模式下,Nginx通过指定的IP地址和端口(例如127.0.0.1:9000)与PHP-FPM通信。在Nginx配置文件中,`fastcgi_pass`指令设置为IP地址和端口号,如`fastcgi_pass 127.0.0.1:9000;`。PHP-FPM容器需要配置为监听这个...

    nginx+php-fpm优化技巧总结

    本文将深入探讨Nginx与php-fpm的优化技巧,主要包括内存参数设置、超时参数设置等内容,帮助读者掌握这一领域的核心技术。 #### 二、Unix域Socket通信 Unix域Socket是一种仅在本地主机之间使用的通信方式,与传统的...

    源码安装nginx+php-fpm+http push测试通过

    在IT行业中,构建高效、可扩展的Web服务是至关重要的,而`Nginx`、`PHP-FPM`和`HTTP Push`技术是实现这一目标的关键组件。本教程将详细介绍如何在`CentOS 5.2`操作系统上,通过源码安装`Nginx`、`PHP-FPM`,并实现`...

    php-fpm.rpm包

    PHP-FPM是PHP FastCGI的进程管理器,它允许Web服务器(如Apache或Nginx)通过FastCGI接口与PHP解释器进行通信,从而处理PHP脚本。在Web开发中,PHP通常被用作服务器端编程语言,用于生成动态网页内容。 PHP-FPM的...

    php-fpm.tar.gz

    PHP-FPM是PHP FastCGI的实现,FastCGI是一种用于Web服务器与动态脚本语言之间通信的协议。相比于传统的CGI,FastCGI提供了更高效的处理方式,因为它能在单个进程中多次处理请求,从而减少每次请求创建新进程带来的...

    ubuntu10.04配置 nginx+php-fpm模式的详解

    `fastcgi_pass`指定了Nginx与PHP-FPM通信的地址和端口。 ### 启动和重启服务 在完成配置后,启动或重启Nginx和PHP-FPM服务: ```bash sudo service nginx start sudo service php5-fpm start ``` 或者,如果你想...

    ubuntu12.04安装Nginx+PHP5(PHP-FPM)+MySQL主机详解.pdf

    - PHP-FPM允许Nginx与PHP进程通信,处理PHP脚本。 4. **配置Nginx以支持PHP** - 编辑Nginx的主配置文件: ``` sudo vi /etc/nginx/nginx.conf ``` - 更新`worker_processes`和`keepalive_timeout`的值,例如...

    windows下 php环境部署 nginx+php-nts+fcgi

    4. **配置Nginx与PHP-FPM通信**:在`nginx.conf`中,添加一个location块,设置对.php文件的处理规则,通过fastcgi_pass指定PHP-FPM监听的端口。 5. **启动服务**:使用`RunHiddenConsole.exe`来启动Nginx和PHP-FPM...

    ubuntu 12.04 安装 Nginx+PHP5 (PHP-FPM) +MySQL主机详解.pdf

    PHP-FPM允许Nginx与PHP进程进行通信,处理PHP脚本。 5. 配置Nginx以支持PHP解析: 打开Nginx主配置文件: ``` sudo vi /etc/nginx/nginx.conf ``` 找到`worker_processes`和`keepalive_timeout`行,根据你的服务器...

    PHP-FPM和Nginx的通信机制详解

    理解PHP-FPM和Nginx的通信机制对于优化Web服务器性能至关重要。通过合理配置Nginx和PHP-FPM,我们可以确保动态内容的快速处理,同时降低系统资源的消耗。选择合适的通信方式(TCP或UNIX socket)取决于具体的部署...

    php5.2.17版本和PHP5.2.17 fpm补丁

    在 Linux 上,特别是与 Nginx 配合时,PHP-FPM 是必要的,因为 Nginx 不直接处理 PHP 脚本,而是通过 FastCGI 协议与 PHP 进程通信。 描述中提到的 "PHP5.2.17 fpm 补丁" 指的是用于将原始 PHP 5.2.17 集成到 FPM ...

    php-fpm中文文档.pdf

    2. FastCGI是一个用于增强Web服务器与应用服务器之间通信的应用程序接口(API)。与传统的CGI相比,FastCGI能够复用已有的进程,从而减少进程创建和销毁带来的性能开销。 3. PHP-FPM支持的Web服务器包括但不限于...

    nginx+php-fpm配置文件的组织结构介绍

    5. PHP-FPM与Nginx的通信机制,包括错误日志记录和慢日志配置。 6. 如何处理常见的Nginx与PHP-FPM配合中的问题,如502 Bad Gateway错误。 了解并掌握这些知识点,能够帮助你更有效地配置和维护Nginx+PHP-FPM的Web...

Global site tag (gtag.js) - Google Analytics