• 欢迎来到本博客,希望可以y一起学习与分享

php php-fpm详解与调优

PHP benz 1周前 (10-06) 14次浏览 0个评论 扫描二维码
文章目录[隐藏]

什么是 php-fpm

CGI,Fast-CGI,CLI,php-cgi,php-fpm
简单来说,php-fpm是用来管理php进程的。php-fpm是主进程(master进程),只负责调度子进程,不处理php;处理php的是子进程(work进程),子进程有很多,为了管理这些子进程,才有了php-fpm。

php-fpm配置

php-fpm的配置文件在php根目录下的/etc文件夹下。
php-fpm的配置文件有两种,一个是php-fpm.conf全局配置文件,另一个是php-fpm.d文件下的www.conf进程池配置文件。php-fpm.conf最后会引入进程池配置include=etc/php-fpm.d/*.conf。不同的进程池可以用不同的用户执行,监听不同的端口,处理不同的任务;多个进程池共用一个全局配置。

php-fpm工作流程

php-fpm全名是PHP FastCGI进程管理器

php-fpm启动后会先读php.ini,然后再读相应的conf配置文件,conf配置可以覆盖php.ini的配置。

启动php-fpm之后,会创建一个master进程,监听9000端口(可配置),master进程又会根据php-fpm.d/www.conf去创建若干子进程,子进程用于处理实际的业务。

当有客户端(比如nginx)来连接9000端口时,空闲子进程会自己去accept,如果子进程全部处于忙碌状态,新进的待accept的连接会被master放进队列里,等待fpm子进程空闲;

这个存放待accept的半连接的队列有多长,由 listen.backlog 配置。

php-fpm全局配置参数

官方注释:FastCGI 进程管理器(FPM)

php-fpm进程池配置 pool Definitions

官方注释:FastCGI 进程管理器(FPM)

在不同的监听端口和不同的管理选项下可以跑任意数量的池,并没有个数限制;

池的名字用于 logs 和 stats。

注意:PHP配置值通过 php_value 或者 php_flag 设置,并且会覆盖以前的值。
disable_functions 或者 disable_classes php.ini 之中定义的值不会被覆盖掉,但是会将新的设置附加在原有值的后面。
使用 php_admin_value 或者 php_admin_flag 定义的值,不能被 PHP 代码中的 ini_set() 覆盖。

自 5.3.3 起,也可以通过 web 服务器设置 PHP 的设定。

php-fpm调优

注意:docker的php-fpm配置在/etc/php-fpm.d文件夹下的zz-docker.conf里配置

nginx 通过 unixsock 与 php-fpm 通信

适用场景:nginx和php-fpm在同一台服务器上,这时可以直接用unixsocket进程间通信,不走tcp端口通信,可以节约创建连接的时间,从而提高性能。

1、设置php-fpm的listen/var/run/php-fpm/php74-fpm.sock(可以用相对路径),然后重启fpm就会自动创建该php74-fpm.sock文件。

docker的在/etc/php-fpm.d文件夹下的zz-docker.conf里配置

2、nginx的fastcgi_pass参数修,需要保证该 php74-fpm.sock 文件 nginx 有权限访问。

总结:

sock文件随便创建到哪里都可以,只要fpm有权限在那个目录里写文件,nginx有权限去读就可以。tcp连接会更稳定,因为有tcp协议保证数据的正确性,但是sock有更少的数据拷贝和上下文切换,更少的资源占用。不过只能在nginx和fpm在同一台机器上才能用sock。

全局配置

指定一段时间内有指定个子进程失效了,PHP-FPM重启:

前两个设置是警告性的,它告诉php-fpm进程,如果 10 个子进程在一分钟内失败,主php-fpm 进程应该重新启动。

这听起来可能不太健壮,但 PHP 是一个会泄漏内存的短命进程,因此在高失败率的情况下重新启动主进程可以解决很多问题。

第三个选项,process_control_timeout告诉子进程在执行从父进程接收到的信号之前等待多长时间。例如,当父进程发送 KILL 信号时,这在子进程处于某事中间的情况下很有用。手头有十秒钟,他们将有更好的机会完成任务并优雅地退出。

配置进程池

fpm运行模式
static:静态模式 启动的fpm进程数固定为 {max_children} 个

dynamic :动态模式 进程数会动态调整 (推荐)

ondemand : 此模式下没有请求时 启动的fpm子进程数为0个 按需启动

每个fpm子进程大概需要占用20m上下的内存 ,并不是开越多越好,还是要根据实际的请求量进行调整,避免fpm占用过多资源

static 模式适合机器配置较好 最好还是独立的 固定多少个 可以节省启动子进程的时间,缺点是比较占用资源

dynamic 模式会动态管理子进程数 ,多退少补。 目前这个模式用的比较多 具体多少个需要看情况

max_requests : 最好不要设置为0 0代表不重启 一般设置2000-5000 次请求重启一次,防止意外的内存泄漏情况

设置 backlog
高并发时,会出现php-fpm线程不够用的情况,此时一般需要调整backlog,之前也分析过:如果worker进程不够用,master进程会prefork更多进程,
如果prefork达到了pm.max_children上限,worker进程又全都繁忙,这时master进程会把请求挂起到连接队列backlog里,而backlog默认值是511,除了加大pm.max_children,调整backlog也是有必要的。

对于PHP而言,需要注意的有3方面:

1、操作系统 | sysctl

2、WEB前端 | 比如:Nginx

3、PHP后台 | 比如:php-fpm

操作系统以CentOS为例,可通过默认配置/etc/sysctl.conf 文件进行调整。比如:

Nginx可通过默认配置 /etc/nginx/nginx.conf 文件中的监听选项来调整:

php-fpm可以通过默认配置 /etc/php-fpm.d/www.conf 文件进行调整。比如:

设置php-fpm单次请求最大执行时间
今天碰到一个问题,测试服务器php-fpm一直是被占满状态,后来发现是set_time_limit(0)file_get_content(),原因如下:

比如file_get_contents(url)等函数,如果网站反应慢,会一直等在那儿不超时,php-fpm一直被占用。有一个参数 max_execution_time 可以设置 PHP 脚本的最大执行时间,但是,在 php-cgi(php-fpm) 中,该参数不会起效。真正能够控制 PHP 脚本最大执行时间的是 php-fpm.conf 配置文件中的以下参数。

默认值为 0 秒,也就是说,PHP 脚本会一直执行下去。这样,当所有的 php-cgi 进程都卡在 file_get_contents() 函数时,这台 Nginx+PHP 的 WebServer 已经无法再处理新的 PHP 请求了,Nginx 将给用户返回“502 Bad Gateway”。可以使用 request_terminate_timeout = 30s,但是如果发生 file_get_contents() 获取网页内容较慢的情况,这就意味着 150 个 php-cgi 进程,每秒钟只能处理 5 个请求,WebServer 同样很难避免“502 Bad Gateway”。php-cgi进程数不够用、php执行时间长、或者是php-cgi进程死掉,都会出现502错误。

要做到彻底解决,只能让 PHP 程序员们改掉直接使用 file_get_contents("http://example.com/") 的习惯,而是稍微修改一下,加个超时时间,用以下方式来实现 HTTP GET 请求。要是觉得麻烦,可以自行将以下代码封装成一个函数。

慢日志查询(辅助)
我们有时候会经常饱受500,502问题困扰。当nginx收到如上错误码时,可以确定后端php-fpm解析php出了某种问题,比如,执行错误,执行超时。

这个时候,我们是可以开启慢日志功能的。

当一个请求该设置的超时时间15秒后,就会将对应的PHP调用堆栈信息完整写入到慢日志中。

php-fpm慢日志会记录下进程号,脚本名称,具体哪个文件哪行代码的哪个函数执行时间过长。

php-fpm进程状态监控(辅助)
1、nginx配置:遇到 status 的请求,直接转发给php

2、/etc/php-fpm.d/www.conf 配置:

3、然后重新fpm和nginx,在浏览器里访问就能看到了:

默认以 text/plain 展示结果,可以传参数 ?json/html/xml 分别得到json等格式的结果;参数full可以查看每个子进程的明细。

pool : 进程池名称

process manager : 进程管理方式

start time : 进程什么时候启动的

start since : 进程已经运行了多少秒

accepted conn : 该池总共accept了多少连接

listen queue : 等待accept的连接的数量

max listen queue : fpm启动后,历史最高等待accept的连接的数量

listen queue len : 配置的监听队列最大长度 受限于listen.backlog和系统cat /proc/sys/net/core/somaxconn,两者中取最小值

idle processes : 闲置的进程数

active process : 正在工作的进程数(加上限制的,就是总的子进程数)

total processes : 总的子进程数量

max active processes : fpm启动后,历史最多同时工作的进程数

max children reached : 进程管理模式为 ‘dynamic’和 ‘ondemand’时,此数值是当子进程不够用时,master创建更多子进程的次数

slow requests : 慢请求个数

full参数下
pid : 子进程ID;

state : 子进程状态(Idle, Running, …);

start time : 子进程启动的时间;

start since : 子进程启动后运行了多少秒;

requests :当前子进程一共处理了多少个请求;

request duration : 请求耗费的纳秒数;

request method : 请求方法 (GET, POST, …);

request URI : 请求参数;

content length : POST请求时,请求的内容长度;

user : 用户 (PHP_AUTH_USER) (or ‘-’ 如果没设置)

script : 请求的哪个php文件;

last request cpu : 上次请求耗费的cpu资源

last request memory :上次请求耗费的内存峰值
如果进程是闲置状态,那这些信息记录的就是上次请求的相关数据,否则就是当前本次请求的相关数据。

 

php-fpm的高CPU使用率排查方法(辅助)
1、使用top命令, 直接执行top命令后,输入1就可以看到各个核心的CPU使用率。而且通过top -d 0.1可以缩短采样时间

2、查询php-fpm慢日志

参数解释:

sort : 对单词进行排序
uniq -c : 显示唯一的行,并在每行行首加上本行在文件中出现的次数
sort -k1,1nr : 按照第一个字段,数值排序,且为逆序
head -10 : 取前10行数据

3、用strace跟踪进程

a、利用nohup将strace转为后台执行,直到attach上的php-fpm进程死掉为止:

参数说明:

-c: 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d: 输出strace关于标准错误的调试信息.
-f: 跟踪由fork调用所产生的子进程.
-o filename: 则所有进程的跟踪结果输出到相应的filename
-F: 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h: 输出简要的帮助信息.
-i: 输出系统调用的入口指针.
-q: 禁止输出关于脱离的消息.
-r: 打印出相对时间关于,,每一个系统调用.
-t: 在输出中的每一行前加上时间信息.
-tt: 在输出中的每一行前加上时间信息,微秒级.
-ttt: 微秒级输出,以秒了表示时间.
-T: 显示每一调用所耗的时间.
-v: 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V: 输出strace的版本信息.
-x: 以十六进制形式输出非标准字符串
-xx: 所有字符串以十六进制形式输出.
-a column: 设置返回值的输出位置.默认为40.
-e execve: 只记录 execve 这类系统调用
-p: 主进程号

b、用利用-c参数让strace帮助汇总,非常方便非常强大!

查看php-fpm启动时间(可以得出执行了多长时间)(辅助)


文章 php php-fpm详解与调优 转载需要注明出处
喜欢 (0)

您必须 登录 才能发表评论!