图解PHP-FPM+Nginx通信原理
PHP-FPM
PHP-FPM的全称是PHP FastCGI Process Manager,PHP-FPM是一个进程管理的实现和运行。 FastCGI进程包含两个进程:主进程和工作进程。只有一个主进程负责监听端口并接收 Nginx 请求,而通常有多个(可配置的)工作进程。每个进程都有一个嵌入式 PHP 解释器,PHP 代码实际上在其中执行。
Nginx
Nginx(“engine x”)是一个强大的 HTTP 和反向代理以及 IMAP/POP3/SMTP 服务器。这里介绍一下什么是正向代理和反向代理。这对于我们理解Nginx非常重要
转发代理
我们以访问Google、Facebook等国外网站为例。我们需要使用VPN来访问国外网站。我们使用VPN来访问国外网站。它实际上是一个代理进程。上图:
VPN 是用户可检测到的(因为用户必须建立连接)。 VPN Google 服务器不会注意到它(Google 服务器只知道有 http 请求)。因此,用户能检测到但服务器检测不到的服务器就是代理服务器(VPN)
反向代理
以Nginx作为反向代理实现负载均衡为例,假设我们是现在访问百度,见图:
当用户访问百度时,所有请求都会到达一个反向代理,这个反向代理将请求分发到特定的后端服务器进行处理。目前,该代理服务器对用户不可见。用户发现百度的服务器正在向他返回结果,而他并不知道代理服务器的存在。换句话说,用户无法察觉,但服务器可以检测到。它被称为反向代理(Nginx)
PHP-FPM+Nginx通信
FastCGI致力于减少Web服务器和CGI程序的数量。由于它们之间的交互,服务器可以同时处理更多的网络请求。与 CGI 为每个请求创建一个新进程不同,FastCGI 使用持久进程来处理多个请求。 这些进程由 FastCGI 进程管理器管理,而不是 Web 服务器。
用图理解PHP-FPM与Nginx的通信 (1)当Nginx收到http请求(动态请求)时,会初始化FastCGI环境。 (如果是Apache服务器,则启用mode_fastcgi模块,如果是Nginx服务器,则启用ngx_http_fastcgi_模块)
(2)我们在配置nginx解析php请求时,通常会有这样一行配置:
fastcgi_pass 127.0.0.1:9000;
复制代码
或者是这样的:
fastcgi_pass unix:/tmp/php-cgi.sock;
复制代码
它实际上是 Nginx 和 PHP-FPM 之间的一种通信媒介(或者说通信方式)。目的是告诉Nginx收到动态请求后将其发送到哪里。 (这两种配置的区别后面会介绍)
(3)Nginx以socket的形式将请求转发给FastCGI主进程
(4)FastCGI主进程选择一个空闲的worker进程进行连接,然后 Nginx 将 CGI 环境变量和标准输入发送给工作进程(php-cgi)
(5) 当工作进程处理完成后,从同一个套接字连接返回标准输出和错误信息 Nginx
(6)worker进程关闭连接,等待下一次连接
从配置角度描述PHP和Nginx之间的通信
- 我们知道Nginx也有host和worker进程,而worker进程直接处理每个web请求
- 其实在Nginx+PHP架构中,php可以认为是cgi程序的角色,所以php-fpm进程管理似乎就是处理这些php请求的。和nginx一样,php-fpm也监听一个端口(从nginx.conf配置我们知道nginx默认监听8080端口,php-fpm默认监听9000端口),并且有master和worker进程。 Worker负责处理每个php请求
- 关于fastcgi:fastcgi是一个协议。市场上有很多实现fastcgi协议的进程管理器,php-fpm就是其中之一。作为fastcgi进程管理服务,php-fpm监听端口。通常它默认侦听端口 9000 和本地计算机,这意味着它只接收来自本地计算机的端口请求。
- 至于fastcgi配置文件,目前的fastcgi配置文件通常放在与nginx.conf同一目录下。通常有两种类型的配置文件:
fastcgi.conf和 fastcgi_params。
不同的nginx版本会有不同的配置文件,这两个配置文件有一个非常重要的区别:fastcgi_parames文件中缺少下列配置:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
复制代码
我们可以打开 fastcgi_params 文件并添加上面的行,或者我们可以在使用配置的地方动态添加它。启用此配置
- 当需要处理php请求时,nginx工作进程将请求交给php-fpm工作进程处理。所以nginx一开始就调用php。其实准确的说是nginx间接调用PHP(反向代理方式)
我的机器上配置了nginx可以正常解析PHP程序。我想介绍一下每行配置的含义
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 $document_root$fastcgi_script_name;
include fastcgi_params;
}
access_log /work/html/logs/test.log;
}
复制代码
- 第一个curly server{ }:代表一个独立的服务器
- listen 8080:代表监听8080端口的服务器
- 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等
- root / work /html/:请求资源根目录,告诉位置对应的uri去/work/html/文件夹中查找同名资源
- fastcgi_pass 127.0.0.1:9000:这一行代码表示您输入。该位置的请求uri被认为是一个cgi程序,请求被发送到端口9000并交给php-fpm进行处理(php-fpm配置看到它正在监听这个端口)
- fastcgi_param SCRIPT_FILENAME fastcgi_script_name;:这行定义的意思是,动态添加一行fastcgi规范,配置内容为SCRIPT_FILENAME,并告诉manager进程cgi脚本的名称。由于我的nginx只有fastcgi_params文件而没有fastcgi.conf文件,为了让php-fpm知道SCRIPT_FILENAME文件的具体值,需要动态添加这行配置行
- 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域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 Sock (这是上面画的 Nginx 和 PHP-FPM 通信的示意图,此时 Nginx 和 PHP-FPM 在同一台机器上)看看 Nginx 和 PHP-FPM 不在同一台机器上的情况: Unix Socket: Nginx配置有很多fasgcgi_*,更多配置可以在同一个ginx目录中看到。会议。在 fastcgi.conf 和 fastcgi_params 中,上面解释了两者之间的区别。查看内部内容: 了解php配置。 fpm,它可以帮助我们正在优化服务器性能 意味着如果在emergency_restart_interval内出现SIGSEGV或SIGBUS错误的php-cgi进程数量超过emergency_restart_threshold,php-fpm将优雅地重启。这两个选项通常保持默认值 设置子进程接受父进程复用信号的超时时间。可用单位:s(秒)、m(分钟)、h(小时)或 d(天) 默认单位:s(秒)。默认:0. fpm监听端口,即php在nginx中处理的地址。通常默认值就足够了。可用格式有:“ip:port”、“port”、“/path/unix/socket”。必须配置每个进程池。 以下配置参数比较重要: php-fpm.conf 是默认的进程池。我们可以打开php-fpm.conf来看一下。以下是我的: 如果要指定多个,请执行以下操作: https: https: ♿♓❓ .ph。 /php-weizijiaoheng-393152.html https://www.cnblogs.com/skynet/p/4173450 .html https://blog.csdn.net/afring/article/details/93880216 https://www.cnblogs. com/ahaii/p/5776809.html 作者:ShulvNginx <=> socket <=> TCP/IP <=> 物理层 <=> 路由器 <=> 物理层 <=> TCP/IP <=> socket <=> PHP-FPM
复制代码
Nginx <=> socket <=> PHP-FPM
复制代码
包含fastcgi_params;
这里的内容是传递给PHP-FPM管理的fastcgi进程的。为什么这些会被传承下来?相信大家都用过全局变量$_SERVER,这里的值就是从这个配置中获取的。我们在fastcgi_params中看到REMOTE_ADDR,这是客户端的地址。 PHP之所以能够获取客户端信息是因为Nginx配置中的fastcgi_params。关于ngx_http_fastcgi_module的更多信息可以参见官方文档:http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html
php-fpm.conf配置
emergency_restart_threshold = 60
emergency_restart_interval = 60s
复制代码
process_control_timeout = 0
复制代码
listen = 127.0.0.1:9000
复制代码
request_slowlog_timeout = 10s
#当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 ’0′ 表示 ‘Off’
slowlog = log/$pool.log.slow
慢请求的记录日志,配合request_slowlog_timeout使用
复制代码
pm
pm指的是process manager,指定进程管理器如何控制子进程的数量,它为必填项,支持3个值
(1)static: 使用固定的子进程数量,由pm.max_children指定(可以同时存活的子进程的最大数量)
(2)dynamic:基于下面的参数动态的调整子进程的数量,至少有一个子进程(会使用下边几个配置)
pm.start_servers: 启动时创建的子进程数量,默认值为min_spare_servers + max_spare_servers - min_spare_servers) / 2
pm.min_spare_servers: 空闲状态的子进程的最小数量,如果不足,新的子进程会被自动创建
pm.max_spare_servers: 空闲状态的子进程的最大数量,如果超过,一些子进程会被杀死
(3)ondemand: 启动时不会创建子进程,当新的请求到达时才创建,有下边两个配置
pm.max_children
pm.process_idle_timeout 子进程的空闲超时时间,如果超时时间到没有新的请求可以服务,则会被杀死
区别:
如果pm设置为 static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程
如果pm设置为 dynamic,那么pm.max_children参数失效,后面3个参数生效
系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程,
然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数
还有一个比较重要的配置:
pm.max_requests
每一个子进程的最大请求服务数量,如果超过了这个值,该子进程会被自动重启。在解决第三方库的内存泄漏问题时,这个参数会很有用。默认值为0,指子进程可以持续不断的服务请求
复制代码
PHP-FPM 进程池
现在运行: ps -aux|grep php -fpm
可以看到有一个主机和 10 个工作进程,和我们指定的一样(www 是进程池名称)
Nginx 中的 Fastcgi_pass 是您指定要使用的进程池的位置
链接:https://juejin.im/post/6861726452917174279s。版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。