php服务器要运行, 很多都是使用php-fpm. 那么优化php-fpm就关系到服务器的性能和稳定, 今天我们来讨论如何优化.
工作流程
首先我们要了解解析php文件的流程, nginx接受到请求, 转发给fpm-master进程, master进程分配任务给fpm-worker进程, fpm-worker进程通过内置的php解析器解析php文件, 最后返回.
可以看出整个流程最大问题在于master和worker进程的配置, 因为nginx的转发过来会被master接手, master接手后会给worker, worker就开始干解析的工作.
优化php.ini
php.ini文件是php解析器用的, 虽然配置会影响到解析速率, 但并不是主要因素, 我们只需要使用常规的第三方模块, 按照常规配置就不会有大问题.
优化php-fpm.conf
php-fpm.conf文件是给master用的, 我们是需要优化的.
php-fpm运行死机时重启
我们想一个问题, 程序都是有Bug的, 万一fpm死循环怎么办呢? 那唯一的办法就是让它重新启动, 这和我们电脑死机重启一个道理. 所以我们第一个优化点就是当php-fpm运行死机时重启.
emergency_restart_threshold 10
emergency_restart_interval 1m
我们在php-fpm.conf
文件中增加上面两行, 这两行的意思是在一分钟内worker进程执行任务失败10次, 重启php-fpm.
master杀死worker前, 让worker交代后事
人会死, worker也会死, 死之前会有一些事情没做完.
process_control_timeout 10s
在php-fpm.conf
添加上面一句话, 在销毁worker前, 给worker10秒钟, 让worker平稳退出.
优化www.conf
以上是master的配置, 还有worker进程池的配置, 那就是我们的www.conf
文件
三种模式选择
workder进程池最重要的就是对于worker数量的控制. 有三种模式, static(固定数量), dynamic(保持一定基数, 动态扩展), ondemand(有请求创建, 没请求销毁).
ondemand是最节约内存的, 只要没请求, worker进程就不创建. 当流量小是没什么问题, 但是流量大时, 要不停的创建销毁worker进程, 会大量消耗CPU资源.
static是最吃内存的配置, 直接开启最多数量的worker, 不管有没有请求都常驻内存, 这样对CPU最友好, 不需要反复创建销毁worker进程.
dynamic是折中的方案, 内存消耗量居中, 它是先开启一定的worker常驻内存, 当请求多时开启更多的worker, 请求少时销毁多余worker.
以上三种方案, ondemand可以不用考虑, 该方案太吃cpu了. 如果你内存不紧张, 能分配固定内存给php-fpm程序, 那推荐是static方案. 如果你主机有多个程序共存, 需要抢内存, 推荐dynamic方案.(www.hedaoshe.com)
static配置
主要是max_children值的设置, 假如有1G的可用内存, 每个worker吃掉30M, 那么就设置33.
pm = static
pm.max_children = 33
dynamic配置
dynamic就比较复杂, 要配置4个参数, 我们还是拿1G总内存, 和每个worker吃掉30M举例.
min_spare_servers
: 最小空闲worker的数量, 这个是用来常驻内存的worker数量, 假设你有90M固定内存给php-fpm, 那么这个值就设置3. 就算没有请求, 这三个worker还是一直存在.
max_spare_servers
: 最大空闲worker的数量, 这个是容许的最多空闲worker数, 只要超过这个数量, 就会销毁多余的worker, 这个没有定数, 我这里设置10
start_servers
: php-fpm启动时的worker数量, 这个值必须居于min_spare_servers
和max_spare_servers
, 否则启动会有问题, 我这里设置6.
max_children
: 和static设置一样, 能容许启动的最大worker数量, 这个值是封顶用的, 可以设置33.
pm = dynamic
pm.max_children = 33
pm.start_servers = 6
pm.min_spare_servers = 3
pm.max_spare_servers = 10
防止worker偷内存
worker内嵌的php解释器有很多第三方模块, 这些模块绝对有bug. 比如说执行完后变量未释放, 当处理了几千个请求后, 就有几千个未释放的变量常驻内存, 这样就导致了内存泄漏. worker刚启动时只有3M, 过一段时间后变成30M, 就是内存泄漏的原因.
那么处理方法很简单, 杀掉这个worker, 创建一个新worker. 下面的配置是说1000次请求后杀掉这个worker.
pm.max_requests = 1000
其他
开启慢日志
当某个php请求过长时, 会写入该日志, 让我们分析
slowlog = /usr/local/var/log/php-fpm.log.slow
request_slowlog_timeout = 5s
总结
基本上进行了以上配置后, php性能就可以得到很大的提升.