- 说明
- 一、php-fpm.conf 文件
- 1.全局配置(Global Options)
- 2.进程池设置(Pool Definitions)
- 二、www.conf 文件
- 1.进程池基本设置+监听设置
- 2.process(干嘛的?)
- 3.进程管理器(process manager,简称pm)
- 4.FPM 运行状态页面(FPM status page)
- 5.日志和请求
- 6.其他
- 总结
- 1.初次安装时,需要更改或可以关注的配置项
- 2.到底选择 static 还数 dynamic?
- 3.慢日志查询
- 4.nginx 通过 unix sock 与 php-fpm 通信
- 5.启用 FPM status page
- 6.backlog 配置问题
- 7.pm.max_children 与 request_terminate_timeout
- 8.其他参考内容
说明
系统:macOS 10.14.6
PHP:homebrew 安装的 PHP8.0.20 (fpm-fcgi)
除了有 php-fpm.conf 配置文件外,通常还有其他的 *.conf 配置文件(也可以不要,直接在 php-fpm.conf 配置)用于配置进程池,不同的进程池可以用不同的用户执行,监听不同的端口,处理不同的任务;多个进程池共用一个全局配置。
关于路径问题,原文是这样说的:
All relative paths in this configuration file are relative to PHP’s install prefix (/usr/local/Cellar/php@8.0/8.0.20). This prefix can be dynamically changed by using the ‘-p’ argument from the command line.
“此配置文件中的所有相对路径都相对于 PHP 的安装前缀。 可以使用命令行中的“-p”参数动态更改此前缀。”。
通过 phpinfo() 看到编译参数 ‘–prefix=/usr/local/Cellar/php@8.0/8.0.20’ ‘–localstatedir=/usr/local/var’
所以我的环境下,prefix=/usr/local/Cellar/php@8.0/8.0.20。按照他的说法,如果我使用以下设置:
pid = run/php-fpm.pid error_log = log/php-fpm.log
那么应该出现以下两个文件
/usr/local/Cellar/php@8.0/8.0.20/run/php-fpm.pid
/usr/local/Cellar/php@8.0/8.0.20/log/php-fpm.log
但实际出现的是以下两个文件
/usr/local/var/run/php-fpm.pid
/usr/local/var/log/php-fpm.log
也就是说这两个指令的相对地址是/usr/local/var(从结果上对应“–localstatedir”)。看原文说明也特别说明了他们的相对地址是 /usr/local/var:
; Pid file ; Note: the default prefix is /usr/local/var ; Default Value: none pid = run/php-fpm.pid ; Error log file ; If it's set to "syslog", log is sent to syslogd instead of being written ; into a local file. ; Note: the default prefix is /usr/local/var ; Default Value: log/php-fpm.log error_log = log/php-fpm.log
不明白是上下文为什么会有这种冲突。难道这两个指令是相对于 localstatedir?不管是他的问题还是我理解的问题,涉及的路径的问题,最好还是直接使用完整路径,放在哪了清晰明了。
一、php-fpm.conf 文件 1.全局配置(Global Options)
pid = /usr/local/var/run/php8.0-fpm.pid #fpm 主进程 pid 存放位置,进程会根据设置自动生成文件 error_log = /usr/local/var/log/php8/php-fpm.log #错误日志存放位置,设置成本地文件即可,进程会根据设置自动生成文件 #若设置成"syslog",日志将发送给 syslogd。(syslogd 不熟悉可以无视) 针对 error_log = syslog 个人建议有明确需要再来关注这两个指令 ;syslog.facility = daemon #用于说明正在记录消息的程序是什么类型, #syslogd 可以对不同类型的 facility(设备)信息采取不同的处理方式。 #当前环境默认:daemon(可能是因为我们通常是以守护进程的方式在运行 fpm)以下是可以被 #识别的值: #kern 内核信息,首先通过 klogd 传递; #user 用户进程; #mail 邮件; #daemon 后台进程; #authpriv 授权信息; #syslog 系统日志; #lpr 打印信息; #news 新闻组信息; #uucp 由uucp生成的信息 #cron 计划和任务信息。 #mark syslog 内部功能用于生成时间戳 #local0----local7 与自定义程序使用,例如使用 local5 做为 ssh 功能 #扩展阅读:https://blog.csdn.net/zyy617532750/article/details/74942090 ;syslog.ident = php-fpm #当启用了多割进程池,这一项负责区分出不同的进程池消息,所有有多个进程池配置时,此项的值应该也不同 #当前环境默认:php-fpm ;log_level = notice #记录日志的级别:alert、error、warning、notice、debug。当前环境默认:notice ;log_limit = 1024 #单行字符数。如果该行超出限制,则换行。当前环境默认:1024。 ;log_buffering = yes 重日志场景关注此项 #google 翻译:日志缓冲指定日志行是否被缓冲,这意味着该行是在单个写入操作中写入的。 #如果值为 false,则数据直接写入文件描述符。这是一个实验性的选项,可以在一些繁重的日志 #记录场景中潜在地提高日志记录性能和内存使用率。如果记录到 syslog,则忽略此选项, #因为它必须始终被缓冲。 #当前环境默认:yes ;emergency_restart_threshold = 0 ;emergency_restart_interval = 0 #表示在 emergency_restart_interval 所设置的时间内(如设置:60s)出现SIGSEGV #或者SIGBUS错误的 php-cgi 进程数如果超过了 emergency_restart_threshold 个, #php-fpm 就会优雅重启。这对于解决加速器共享内存中的意外损坏非常有用。 #这两个选项一般保持默认值。0 表示 “关闭该功能”。 当前环境默认: 0 (关闭)。 ;process_control_timeout = 0 #设置子进程等待主进程对信号做出反应的超时时间。 #默认单位:s(秒)。 默认值:0(不限制超时时间)。 ; process.max = 0 #允许 FPM 可 fork 出的进程的最大数。 #当开启了多个进程池并在多个进程池中使用动态 PM(下面有讲)时, #用来限制全局进程数。谨慎使用。默认:0,没有限制 ; process.priority = -19 #设置子进程的优先级,在 master 进程以 root 用户启动时有效;如果没有设置,子进程会 #继承 master 进程的优先级,值范围-19(最高)到20(最低),默认不设置。 daemonize = yes #设置 yes,FPM 将在后台运行; #设置 no,FPM将在前台运行,此模式有助于调试时及时展示错误信息 当程序提示打开文件数量受到限制时,关注这两项。 在一些并发或多线程情况下,需要突破这个限制。 ;rlimit_files = 1024 #设置 master 进程最多能打开的文件数。nginx.conf中也能看到相关指令。默认为系统的值。 ;rlimit_core = 0 #设置 master 进程核心 rlimit 限制值;可选 unlimited 或 >=0 的整数,默认为系统的值。 #ulimit -n 和-u 可以查看 linux 的最大进程数和最大文件打开数。 ;events.mechanism = epoll #一直不知道干嘛的 默认自动检测 # Specify the event mechanism FPM will use. The following is available: # - select (any POSIX os) # - poll (any POSIX os) # - epoll (linux >= 2.5.44) # - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) # - /dev/poll (Solaris >= 7) # - port (Solaris >= 10) ;systemd_interval = 10 #当 fpm 被设置为系统服务时,多久向服务器报告一次运行报告,单位有s、m、h。 #默认单位s,默认值10。(原来程序也要打卡上班的)默认即可,不用管他。2.进程池设置(Pool Definitions)
#在不同的监听端口和不同的管理选项下可以跑任意数量的池,并没有个数限制; #进程池的名字用于 标记哪些属于本进程池进程的日志和统计数据。 #像 nginx 可以把不同的虚拟主机的配置写在自己的文件中然后再通过 include 引入一样 #多个进程池配置也可以单独写进不同的文件,引入文件时可以写相对路径,也可以写绝对路径 #默认只有 www.conf include=/usr/local/etc/php/8.0/php-fpm.d/*.conf
二、www.conf 文件 1.进程池基本设置+监听设置当前环境下 include 引入的文件是 /usr/local/etc/php/8.0/php-fpm.d/www.conf 下文继续介绍 www.conf
[www] #启动一个名为'www'的进程池,这个值会写入$pool变量,可以在本文中任何指令中使用, #需要使用进程池名称的地方,都可以直接使用$pool作为代替。 ;prefix = /path/to/pools/$pool 使用相对路径时关注下 #本配置文件中的相对路径前缀 prefix,默认不设置,将使用全局默认 prefix #一般我喜欢设置完整路径 #只影响下面的指令(如果它们设置的是相对路径的话): # - 'access.log' # - 'slowlog' # - 'listen' (unixsocket) # - 'chroot' # - 'chdir' # - 'php_values' # - 'php_admin_values' user = nobody group = nobody #设置 worker 进程启动时的 user 和 group,必须要设置 user,而 group 在未设置的情 #况下,默认使用 user 所在的 group,默认都是 nobody,一般系统中也会存在这个用户和组 listen = 127.0.0.1:9999 #监听的 ip 和端口号。 #可以的格式如下: # 'ip.add.re.ss:port' - 通过 a TCP socket 监听 IPv4:port # '[ip:6:addr:ess]:port' - 通过 a TCP socket 监听 IPv6:port # 'port' - 通过 a TCP socket 监听 以上所有地址类型 # '/path/to/unix/socket' - 通过 a unix socket 监听 ;listen.backlog = 511 高并发时关注(注释是抄的,我没太理解) #设置 listen(2) 函数的 backlog 参数值,默认: 511。 #未 accept 处理的 socket 队列大小,-1 on FreeBSD and OpenBSD,其他平台默认 #65535,高并发时重要,合理设置会及时处理排队的请求;太大会积压太多,处理完后 #nginx 在前面都等超时断开这个和 fpm 的 socket 连接了,就杯具了。 #不要用-1,建议1024以上,最好是2的幂值。 #一个池共用一个 backlog 队列,所有的池进程都去这个队列里 accept 连接。 #最大数量受限于系统配置 cat /proc/sys/net/core/somaxconn,系统配置修改: #vim /etc/sysctl.conf,增加 net.core.somaxconn = 2000 则最大为2000, #然后 php 最大的 backlog 可以到2000。 #http://blog.chinaunix.net/uid-28541347-id-5748886.html 针对 unix socket 连接方式的设置 ;listen.owner = nobody ;listen.group = nobody ;listen.mode = 0660 #用 unix socket 连接方式时,指定拥有 unix socket 权限的用户, #默认和运行的用户一样;用 tcp 连接可以注释掉 ;listen.acl_users = ;listen.acl_groups = #当支持 POSIX 访问控制列表时,您可以使用这些选项设置它们,值是用逗号分隔的用户/组 #名称的列表。 设置后,listen.owner 和 listen.group 将被忽略 ;listen.allowed_clients = 127.0.0.1 #设置允许连接 fpm 的地址,多个地址用逗号隔开,如果不配置,则默认任意地址都能来连。 默认:any,任何主机都可以连接。仅对 tcp socket 有意义。 # Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable # in the original PHP FCGI (5.2.2+).2.process(干嘛的?)
; process.priority = -19 不理解优先级的用途,默认就好 #set nice(2) priority 参数。 #池进程的权限,同样要 master 进程是 root 用户才有效,和全局那个一样, #不设置的话会继承 master 进程的优先级。默认不设置。 ; process.dumpable = no 不知道实际用途,默认就好 #即使进程用户或组不同于主进程用户,也要设置进程可转储标志 (PR_SET_DUMPABLE prctl)。 #它允许为池用户创建进程核心转储和 ptrace 进程。默认值:no3.进程管理器(process manager,简称pm)
pm = dynamic #决定进程管理器以哪种算法来控制进程数量,提供了三种算法: #static - 固定数量,数值由 pm.max_children 确定; #dynamic - 子进程的数量是根据以下指令动态设置的。有了这个流程管理,总会有至少1个子进程: # pm.max_children - 可以同时活跃的最大子进程数。 # pm.start_servers - fpm 启动时创建的子进程数量(就是初始值) # pm.min_spare_servers - 空闲子进程的最小值,低于这个值就会创建新的子进程 # pm.max_spare_servers - 空闲子进程的最大值,高于这个值就会kill部分子进程 #ondemand - fpm 启动时不创建子进程. 有连接请求时才会创建子进程,涉及指令: # pm.max_children - 可以同时活跃的最大子进程数。 # pm.process_idle_timeout - 指定空闲进程空闲多久后被killed #默认dynamic 小内存建议dynamic 8G以上建议static 因为创建和回收进程也是有开销的 #pm.max_children 等效于带有 mpm_prefork 的 ApacheMaxClients 指令。等效于原始 #PHP CGI 中的 PHP_FCGI_CHILDREN 环境变量。以下默认值基于没有太多资源的服务器。 pm.max_children = 5 #dynamic static ondemand pm.start_servers = 2 #dynamic #计算公式:(min_spare_servers + max_spare_servers) / 2 pm.min_spare_servers = 1 #dynamic pm.max_spare_servers = 3 #dynamic ;pm.process_idle_timeout = 10s; #ondemand 默认值10s ;pm.max_requests = 500 #每个子进程最大处理500请求就被回收,可防止内存泄露。默认没有开启,进程永远不重启。 #等效于 PHP_FCGI_MAX_REQUESTS4.FPM 运行状态页面(FPM status page)
非常有意思的功能(默认关闭状态),fpm 提供了获取进程运行状态的入口,并提供了一个静态页面来展示这些数据。文章结尾有设置参考
;pm.status_path = /status #负责开启或关闭 FPM status page ;pm.status_listen = 127.0.0.1:9001 #这是干嘛的 反正默认就好了 ;ping.path = /ping #FPM 监控页面的 ping 网址。 如果没有设置,则无法访问 ping 页面。该页面用于外部 #检测 FPM 是否存活并且可以响应请求。请注意必须以斜线开头 (/)。默认没有设置 ;ping.response = pong #用于定义 ping 请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本。 #默认值:pong。5.日志和请求
;access.log = log/$pool.access.log
#类似于 nginx 的访问日志,fpm 也有访问日志,每次有请求过来都可以记录日志,默认关闭
;access.format = "%R - %u %t "%m %r%Q%q" %s %f %{mili}d %{kilo}M %C%%"
#此处定义访问日志的格式,具体格式参见原文
;slowlog = log/$pool.log.slow #php慢日志 默认关闭
;request_slowlog_timeout = 0 #超过指定时间的请求将被写进慢日志 默认0
;request_slowlog_trace_depth = 20 #慢日志堆栈信息深度 默认20
;request_terminate_timeout = 0
#设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为
#某些特殊原因没有中止运行的脚本有用. 设置为 '0' 表示 'Off'.当经常出现502错误时可以尝试
#更改此选项。默认为0
;request_terminate_timeout_track_finished = no
# 在应用程序调用 'fastcgi_finish_request' 或应用程序完成并调用关闭函数(通过
# register_shutdown_function 注册)后,不使用 'request_terminate_timeout' ini
# 选项设置的超时。 即使在这种情况下,此选项也将启用无条件应用超时限制。 默认no关闭
#和上面含义一样 按照上下文的意思 只限制当前线程池 默认系统默认值
;rlimit_files = 1024
;rlimit_core = 0
6.其他
;chroot = #启动时的chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用. #默认没有设置 ;chdir = /var/www #设置启动目录,启动时会自动chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录, #或者/目录(chroot时) #注意:chroot和chdir是两个系统命令,开启这两项时,php-fpm在启动时会执行这两个命令,而参数值就是此处设置的值,至于实际用途不是很理解,暂时保持默认好了。 ;catch_workers_output = yes #重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout #和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: no. ;decorate_workers_output = yes #使用前缀和后缀装饰工作输出,其中包含有关写入日志的子节点的信息,以及是否使用了 stdout 或 #stderr 以及日志级别和时间。 仅当 catch_workers_output 为 yes 时才使用此选项。 #设置为“no”将输出写入 stdout 或 stderr 的数据。 ;clear_env = no #清理环境 默认yes 默认即可 ;security.limit_extensions = .php .php3 .php4 .php5 .php7 #设置fpm执行解析的扩展名 默认 .php #传递环境变量,如 LD_LIBRARY_PATH。 所有 $VARIABLEs 都取自当前环境。 ; Default Value: clean env ;env[HOSTNAME] = $HOSTNAME ;env[PATH] = /usr/local/bin:/usr/bin:/bin ;env[TMP] = /tmp ;env[TMPDIR] = /tmp ;env[TEMP] = /tmp #php.ini 的附加设置,只应用于这个进程池。这些设置会覆盖之前在 php.ini 中定义的值。 #此处若定义 disable_functions 或者 disable_classes ,会将新的设置附加在原有值的后面。 #使用 php_admin_value 或者 php_admin_flag 定义的值,不能被 PHP 代码中的 ini_set() 覆盖。 ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com ;php_flag[display_errors] = off ;php_admin_value[error_log] = /var/log/fpm-php.www.log ;php_admin_flag[log_errors] = on ;php_admin_value[memory_limit] = 32M
总结 1.初次安装时,需要更改或可以关注的配置项
pid = /usr/local/var/run/php8.0-fpm.pid
error_log = /usr/local/var/log/php8/php-fpm.log
log_level = notice
daemonize = yes
user = nobody
group = nobody
listen = 127.0.0.1:9999
listen.allowed_clients = ipaddress_1,ipaddress_2,127.0.0.1,...
pm = dynamic 同时关注下其他相关设置
pm.max_requests = 0 按需要选择是否开启
访问日志 默认关闭
access.log = log/$pool.access.log 按需要选择是否开启
access.format = "%R - %u %t "%m %r%Q%q" %s %f %{mili}d %{kilo}M %C%%"
慢日志 默认关闭
slowlog = log/$pool.log.slow
request_slowlog_timeout = 15
request_slowlog_trace_depth = 20
2.到底选择 static 还数 dynamic?
一般原则是:动态适合小内存机器,灵活分配进程,省内存。静态适用于大内存机器,动态创建回收进程对服务器资源也是一种消耗。
如果你的内存很大,有8-20G,按照一个 php-fpm 进程 20M 算,100个就2G内存了,那就可以开启 static 模式。如果你的内存很小,比如才256M,那就要小心设置了,因为你的机器里面的其他的进程也算需要占用内存的,所以设置成 dynamic 是最好的,比如:pm.max_chindren = 8, 占用内存160M左右,而且可以随时变化,对于一般访问量的网站足够了。
3.慢日志查询文本出处
我们有时候会经常饱受500,502问题困扰。当 Nginx 收到如上错误码时,可以确定后端 php-fpm 解析 php 出了某种问题,比如,执行错误,执行超时。
这个时候,我们是可以开启慢日志功能的。
slowlog = /usr/local/var/log/php-fpm.log.slow
request_slowlog_timeout = 15s
当一个请求该设置的超时时间15秒后,就会将对应的PHP调用堆栈信息完整写入到慢日志中。
php-fpm慢日志会记录下进程号,脚本名称,具体哪个文件哪行代码的哪个函数执行时间过长:
[21-Nov-2013 14:30:38] [pool www] pid 11877
script_filename = /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php
[0xb70fb88c] file_get_contents() /usr/local/lnmp/nginx/html/www.quancha.cn/www/fyzb.php:2
通过日志,我们就可以知道第2行的 file_get_contents 函数有点问题,这样我们就能追踪问题了。
4.nginx 通过 unix sock 与 php-fpm 通信文本出处
适用场景:nginx 和 php-fpm 在同一台服务器上,这时可以直接用 unixs ocket 进行进程间通信,不走 tcp 端口通信,可以节约创建连接的时间,从而提高性能。
1、设置 php-fpm 的 listen 为 /you_path/php-fpm.sock,然后重启 fpm 就会自动创建该文件
2、nginx 的 fastcgi_pass 参数修改为 unix:/you_path/php-fpm.sock;通过 php-fpm.sock 文件去和 fpm 通信,需要保证该 nginx 有权限访问 php-fpm.sock 文件 。
sock 文件随便创建到哪里都可以,只要 fpm 有权限在那个目录里写文件,nginx有权限去读就可以。tcp 连接会更稳定,因为有 tcp 协议保证数据的正确性,但是sock 有更少的数据拷贝和上下文切换,更少的资源占用。不过只能在 nginx 和fpm 在同一台机器上才能用 sock。
5.启用 FPM status page6.backlog 配置问题相关配置参考此处
另一处参考
注意:使用file://协议访问 status.html 时,要解决跨域问题
一个 fpm 子进程在同一时间只能处理一个请求,如果 backlog 设置得过大,nginx之类的客户端发起的请求一直没有 fpm 子进程进行 accept,nginx 就会直接断掉这个连接,等 fpm 忙过来了再去 accept 的时候,就会发现断开了,于是报错。backlog 设置得过小,访问量大时 fpm 子进程全部处于忙碌状态,backlog 也塞满了,就会拒绝新的连接,此时 nginx 再请求,就会直接被拒。所以需要合理的设置 backlog 参数。
大部分参数只要系统默认的就可以了,我们只需要知道几个比较重要的参数设置,什么时候用到可以回头查询相关说明
7.pm.max_children 与 request_terminate_timeout在php-fpm的配置文件中,有两个指令非常重要,就是"pm.max_children" 和 “request_terminate_timeout”
第一个指令"pm.max_children" 确定了php-fpm的处理能力,原则上时越多越好,但这个是在内存足够打的前提下,每开启一个php-fpm进程要占用近30M左右的内存
如果请求访问较多,那么可能会出现502,504错误。对于502错误来说,属于繁忙进程而造成的,对于504来说,就是客户发送的请求在限定的时间内没有得到相应,过多的请求导致“504 Gateway Time-out”。这里也有可能是服务器带宽问题。
另外一个需要注意的指令"request_terminate_timeout",它决定php-fpm进程的连接/发送和读取的时间,如果设置过小很容易出现"502 Bad Gateway" 和 “504 Gateway Time-out”,默认为0,就是说没有启用,不加限制,但是这种设置前提是你的php-fpm足够健康,这个需要根据实际情况加以限定。
8.其他参考内容其他参考页 *php-fpm超时时间设置request_terminate_timeout分析
一分钟了解PHP-FPM配置及使用总结



