1. 概述
对于PHP服务而言,nginx php-fpm 是常用的服务配置,如何进行服务器性能调优是一个服务端开发的必备技能。
2. nginx 与 PHP-FPM 的通信
nginx 是通过 fastcgi 与 php-fpm 通信的,他的连接是通过 socket 的方式实现的。 在安装 php-fpm 后,默认他监听了 localhost:9000 的 TCP 端口。 TCP 连接的通信效率要比 UNIX 域协议的通信效率低很多,因此,我们首先通过配置将 nginx 与 php-fpm 的通信改为 UNIX 域协议,可以实现优化。
2.1. nginx 配置
代码语言:javascript复制location ~ .*.(php|php5)?$ {
root /var/www;
fastcgi_pass unix:/dev/shm/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
include fastcgi_params;
}
2.2. php-fpm 配置
代码语言:javascript复制listen = /dev/shm/php-cgi.sock
顺次重启 php-fpm 和 nginx 就实现了通信。
也许你会发现访问返回了 502 bad gate way。 这是因为 unix 域协议文件没有权限访问,可以通过 chmod 改变 /dev/shm/php-cgi.sock 文件的权限解决。
3. nginx worker 数
通过 nginx 配置中的 worker_processes 可以指定 nginx 运行时的 worker 数量,默认在运行 ./configure 的时候会检测硬件将该配置设为 CPU 核心数。 理论上说,worker 越多,处理请求的能力越强,由于 worker_cpu_affinity 将 nginx 的 worker 与 CPU 核心绑定执行,这使得 worker 可以使用 CPU 缓存,避免了上下文切换带来的开销,因此,不要让 worker 数小于 CPU 核心数是最起码的要求,否则多个核心切换时会带来不必要的开销。 测试结果表明,nginx worker 数是 CPU 核心数的 2 倍时性能最优。
4. backlog 的设置
大量并发的场景中,常常会出现 nginx 返回: connect() to unix:/tmp/php-fpm.socket failed (11: Resource temporarily unavailable) while connecting to upstream。 这意味着 php-fpm 停止停止接收任务了。 避免这个问题,就要在 php-fpm 的配置上着手了。
首先,通过调整 nginx、php-fpm 和系统内核的 backlog,可以让 socket 通信积压更大,从而缓解这个压力。 如在 nginx server 块配置中加入:
代码语言:javascript复制listen 80 default backlog=1024;
在 php-fpm 配置中加入:
代码语言:javascript复制listen.backlog = 2048
并将 /etc/sysctl.conf 文件中相关配置改为:
代码语言:javascript复制net.ipv4.tcp_max_syn_backlog = 4096
net.core.netdev_max_backlog = 4096
5. 增加 PHP-FPM worker 数
关于 php-fpm 的 worker 数,有如下四个参数:
- pm.max_children — 静态方式下开启的 php-fpm 进程数量
- pm.start_servers — 动态方式下的起始 php-fpm 进程数量
- pm.min_spare_servers — 动态方式下的最小 php-fpm 进程数量
- pm.max_spare_servers — 动态方式下的最大 php-fpm 进程数量
通过制定 pm 参数为 static 或 dynamic,php-fpm 会应用上述对应的配置数。 通过将 php-fpm 的 worker 数设置增大,可以增加他的并发能力。 长期运行中,每个 php-fpm worker 占用内存约 30MB 左右,worker 数的具体大小需要根据系统的内存总量控制,否则可能造成系统被拖垮。
6. 定时重启 php-fpm
与 Apache 一样,php-fpm 也有内存泄露的问题,因此定时重启也可以增加系统的性能。 在 crontab 中写入定时的 php-fpm restart 或 reload 是一个很方便的措施。
7. 配置 php-fpm 关闭执行时间限制
通过 php-fpm 配置:
代码语言:javascript复制request_terminate_timeout = 0
去除 PHP 执行时间限制,不会在 PHP 执行过程中由于超时中止 PHP 的执行。 同时,需要对 PHP 的 max_execution_time 选项进行设置。
8. 配置 php-fpm 查看返回错误
通过 php-fpm 配置:
代码语言:javascript复制catch_workers_output = yes
这个配置将运行中的 stdout 和 stderr 输出到主要的错误日志文件中。 如果没有设置这个选项,stdout 和 stderr 会被重定向到 /dev/null。