Nginx与php-fpm之间的通信机制

image.png

理解一个完整的PHP请求前,需要搞明白cgi、php-cgi、fastcgi、php-fpm的相关概念

cgi协议:

cgi协议是用来确定web服务器(如NGINX)和CGI应用程序(如PHP),是保证web server传递过来的数据是标准格式的,方便CGI程序编写。

php-cgi进程解释器:

php-cgi是php的cgi协议进程解释器,进程就是程序的工作单位。进程每次启动时,需要经历加载php.ini文件->初始化执行环境->处理请求->返回内容给web服务器->php-cgi进程退出的流程。

Fast-cgi协议:

Fast-cgi协议是对cgi协议效率提升的补充,主要是针对每次请求过来时都需要启动一个cgi解释器进程的优化,不需要cgi解释器进程每次收到web服务器请求后秋需要重新加载php.ini文件和初始化执行环境。

php-fmp进程管理器:

php-fpm是对fast-cgi协议的实现,是进程管理器,启动时包括master进程和work进程两部分,master进程负责监听端口,接收来自web服务器的请求,worker进程一般有多个,每个worker进程都有一个cgi进程解释器,用来执行php代码。

php-fpm即php-Fastcgi Process Manager。php-fpm是 FastCGI 的实现,并提供了进程管理的功能。进程包含 master 进程和 worker 进程两种进程。master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个PHP解释器,是PHP代码真正执行的地方。

php脚本执行原理过程:

启动php-fpm时,会启动master进程,加载php.ini文件,初始化执行环境,并启动多个worker进程。每次接收的web请求时,将会将web请求传递给work进程进行处理。

完整的流程:

用户访问URL地址->域名进行DNS解析->请求到对应的IP服务器和端口->NGINX监听对应的端口请求->NGINX对url进行location匹配->执行匹配location下的规则->NGINX转发请求给php->php-fpm的master进程监听到NGINX请求->master进程将请求分配给一个闲置的worker进程->worker进程执行请求->worker进程返回执行结果给NGINX->NGINX返回结果给用户

image.png

PHP-FPM+Nginx通信示意图

image.png

1、当Nginx收到http请求(动态请求),它会初始化FastCGI环境。(如果是Apache服务器,则初始化mode_fastcgi模块、如果是Nginx服务器则初始化ngx_http_fastcgi_module)

2、我们在配置nginx解析php请求时,一般会有这样一行配置:

fastcgi_pass 172.0.0.1:9000

或者长这样:

fastcgi_pass unix:/tmp/php-cgi.sock;

它其实是Nginx和PHP-FPM一个通信载体(或者说通信方式),目的是为了让Nginx知道,收到动态请求之后该往哪儿发。(关于这两种配置的区别,后边会专门介绍)

3、Nginx将请求采用socket的方式转给FastCGI主进程

4、FastCGI主进程选择一个空闲的worker进程连接,然后Nginx将CGI环境变量和标准输入发送该worker进程(php-cgi)

5、worker进程完成处理后将标准输出和错误信息从同一socket连接返回给Nginx。

6、worker进程关闭连接,等待下一个连接

image.png

从配置的角度,再描述一下PHP和Nginx的通信

1、我们知道Nginx也是有master和worker进程的,worker进程直接处理每一个网络请求

2、其实在Nginx+PHP的架构里边,php可以看做是一个cgi程序的角色,因此出现了php-fpm进程管理器来处理这些php请求。php-fpm和nginx一样,也会监听端口(通过nginx.con里的配置我们知道,nginx默认监听8080端口,php-fpm默认监听9000端口),并且有master和worker进程,worker负责处理每一个php请求。

3、关于fastcgi:fastcgi是一个协议。市面上有多种实现了fastcgi协议的进程管理器,php-fpm就是其中的一种。php-fpm作为一种fastcgi进程管理服务,会监听端口,一般默认监听9000端口,并且是监听本机,也就是只接收来自本机的端口请求。

4、关于fastcgi的配置文件,fastcgi的配置文件一般放在nginx.conf同级目录下,配置文件形式,一般有两种:

fastcgi.conf和 fastcgi_params。

不同的nginx版本会有不同的配置文件,这两个配置文件有一个非常重要的区别:fastcgi_parames文件中缺少下列配置:

fastcgi_param SCRIPT_FILENAME fastcgi_script_name;

我们可以打开fastcgi_params文件加上上述行,也可以在要使用配置的地方动态添加。使得该配置生效。

5、当需要处理php请求时,nginx的worker进程会将请求移交给php-fpm的worker进程进行处理,也就是最开头所说的nginx调用了php,其实严格的讲是nginx间接调用php(反向代理的方式)。

我本机配置了能正常解析php程序的nginx配置,解释一下每一行配置的含义:

server{

listen 8080;

index index.php

root /work/html/;

location ~ [^/].php(/|$)

{

root /work/html/;

fastcgi_pass 127.0.0.1:9000;

fastcgi_param SCRIPT_FILENAME fastcgi_script_name;

include fastcgi_params;

}

access_log /work/html/logs/test.log;

}

1、第一个大括号 server{ }:代表一个独立的server

2、listen 8080:代表该server监听8080端口

3、location ~ [^/].php(/|$){ }:代表一个能匹配对应uri的location,用于匹配一类uri,并对所匹配的uri请求做自定义的逻辑、配置。这里的location,匹配了所有带.php的uri请求,例如:http://192.168.244.128:8011/test.php/asdasd http://192.168.244.128:8011/index.php等

4、root /work/html/:请求资源根目录,告诉匹配到该location下的uri到/work/html/文件夹下去寻找同名资源。

5、fastcgi_pass 127.0.0.1:9000:这行代码的意思是,将进入到该location内的uri请求看做是cgi程序,并将请求发送到9000端口,交由php-fpm处理(php-fpm配置中会看见它监听了此端口)。

6、fastcgi_param SCRIPT_FILENAME

fastcgi_script_name; :这行配置意思是:动态添加了一行fastcgi配置,配置内容为SCRIPT_FILENAME,告知管理进程,cgi脚本名称。由于我的nginx中只有fastcgi_params文件,没有fastcgi.conf文件,所以要使php-fpm知道SCRIPT_FILENAME的具体值,就必须要动态的添加这行配置。

7、include fastcgi_params; 引入fastcgi配置文件

fastcgi_pass

Nginx和PHP-FPM的进程间通信有两种方式,一种是TCP Socket,一种是Unix Socket

Tcp Socket方式是IP加端口,可以跨服务器.而UNIX Socket不经过网络,只能用于Nginx跟PHP-FPM都在同一服务器的场景,用哪种取决于你的PHP-FPM配置

Tcp Socket方式:

nginx.conf中配置:fastcgi_pass 127.0.0.1:9000;

php-fpm.conf中配置:listen=127.0.0.1:9000;

Unix Domain Socket方式:

nginx.conf中配置:fastcgi_pass unix:/tmp/php-fpm.sock;

php-fpm中配置:listen = /tmp/php-fpm.sock;

(php-fpm.sock是一个文件,由php-fpm生成)

举例:

两种通信配置方式,Nginx和PHP-FPM的通信过程如下:

Tcp Socket:

Nginx <=> socket <=> TCP/IP <=> socket <=> PHP-FPM

(上边画Nginx和PHP-FPM通信的图时就是这种方式,这种情况是Nginx和PHP-FPM在同一台机器上)

看一下Nginx和PHP-FPM不在同一台机器上的情况:

Nginx <=> socket <=> TCP/IP <=> 物理层 <=> 路由器 <=> 物理层 <=> TCP/IP <=> socket <=> PHP-FPM

Unix Socket:

Nginx <=> socket <=> PHP-FPM

你可能感兴趣的:(Nginx与php-fpm之间的通信机制)