上周报名了一个活动,结果对方服务器nginx 502了,有朋友进去了活动页面,我都没进得去!后来听说是php配置文件没配置好,导致了这个问题。
正好最近入了php的坑,就来学习一些php配置里面可能会导致服务器nginx 502的地方。
nginx 502 一般是以下几种情况:
- php-fpm进程没有启动,或者nginx的fastcgi_pass设置错误,导致nginx连不到php
- php worker进程不够,请求太多处理不过来
- php-fpm执行超时,被kill掉,导致nginx与其连接被断开
nginx 504 一般是以下情况:
- 虽然php脚本还在执行,但nginx与上游通信时间超时。
下面就来以此解决这几个问题:
一、 php-fpm进程或者nginx fastcgi_pass配置
确认php-fpm是否已启动,可使用命令ps aux|grep php-fpm
查看进程
确认nginx
的fastcgi_pass
是否正确:
- 先确认php-fpm已启动
- fastcgi_pass有两种形式
ip:port
。(如:127.0.0.1:9000)这种方式使用TCP链接,会经过网络请求。unix socket
.(如:unix:/home/users/nemo/php/var/run/php-cgi.sock)这种方式不会进行网络请求,而是在内部发送系统信息。- 一般情况下,这两种方式都可以,性能差别不大。如果要提高一下性能,就使用unix socket的形式。如果要请求非本机的php-fpm,那么只能使用
ip:port
的形式。 - 具体你的php-fpm使用的是哪种形式,可以在配置文件
php-fpm.conf
里面,listen
属性里面查看。
二、php的worker进程不够,请求太多,处理不过来
最简单粗暴的,就是在php-fpm.conf
里面增加pm.max_children
的个数。
但是,这里要考虑到内存占用的问题。关于内存,有几个方面:
php.ini
里面的memory_limit
表示的是一个php-cgi进程最多占用的内存。每个请求完成后php-cgi会回收内存,但是不会释放给操作系统,这样就会导致大量内存被php-cgi占用- 在代码里面,可以临时设置当前脚本最大占用的内存,如
ini_set('memory_limit', 20M)
- 假如说,每个php-cgi即worker进程,占20M内存,那么5个worker的话就占100M内存。
- 当服务器请求很多的时候,5个进程全部在处理任务,对很多只有128M的虚拟主机(
vhost
)来说,如果还要处理其他程序,内存很可能很吃紧。
下面就来说说,如何配置worker的个数。
pm
:它有三种模式,static
, dynamic
, ondemand
。下面来说说这三种模式的区别:
dynamic
模式:php-fpm启动时,会产生固定数量(由pm.start_servers
决定)的worker进程,而最大子进程数由pm.max_children
决定。其中pm.max_spare_servers
是最大空闲子进程数,当空闲的worker数超过pm.max_spare_servers
时,就会把多余的杀掉。而pm.min_spare_servers
是最小空闲子进程数,当空闲子进程小于pm.min_spare_servers
,则会新增worker进程。
在dynamic
模式下,可能会存在一种现象,比如,高峰期过了之后,内存占用还是没有少。重启之后就少了。
举例来说:比如pm.max_children = 50
,pm.max_spare_servers = 35
,pm.min_spare_servers = 5
,高峰期时,50个worker都在处理任务,高峰期过了之后,woker都闲置了,根据pm.max_spare_servers
会有15个worker被杀掉,仍有35个worker进程闲置,并且占用着内存。这就是高峰期过后,内存仍然高居不下的原因。
当重启之后,根据pm.min_spare_servers
会产生5个新的worker。这就是高峰期过后重启之后,内存占用显著变小的原因。
static
模式:始终保持一个固定数量的woker进程,数量由pm.max_children
定义。其他配置,如pm.start_servers
等都用不上。
ondemand
模式:该模式下,只有pm.max_children
和pm.process_idle_timeout
有用。php-fpm启动的时候,只会创建master,不会创建worker。当请求来的时候,再创建worker,pm.max_children
决定最大worker进程数。而pm.process_idle_timeout
决定闲置进程在持续闲置了多少秒
之后就会被杀掉。
在ondemand
模式下,如果高峰期请求非常大,那么就会频繁地创建worker进程,产生很多不必要的消耗。如果长时间没请求,那么就只会有一个php-fpm主进程
一般默认的模式是dynamic
,具体采用什么模式,使用什么配置,还需要根据自己的机器来设定。
本文一开始说的因php配置产生nginx 502的问题,应该就是当请求量很大,又没有内存生成新的worker的时候,会产生nginx 502问题。
还有一个参数pm.max_requests
,与worker进程个数无关,但也可能引起nginx 502。pm.max_requests
表示每个子进程重生之前处理的请求数,对于可能存在内存泄漏的第三方模块来说非常有用。如果设置为 '0' 则表示一直接受请求。等同于 PHP_FCGI_MAX_REQUESTS
环境变量。当某些php模块存在内存泄露,导致内存占用很高时,无法再处理新的请求,就会nginx 502。
三、php-fpm执行超时
php-fpm.conf
里面有参数request_terminate_timeout
,这个参数设置的是fastcgi花费的所有时间。如果超过了这个时间,那么就会将php-fpm kill掉,并返回502 Bad Gateway
。默认这个参数是0
,表示不设置超时时间。
php.ini
里面的max_execution_time
设置了每个脚本最多执行的时间(单位是 秒
),这里仅仅指代码本身执行的之间,不包括网络请求、数据库查询、系统调用、sleep等。默认这个值是30s
,如果超过这个时间,会产生Fatal: Maximun execution time
错误,会返回500 Internal Server Error
。
nginx 里面也有超时配置:
fastcgi_connect_timeout
。nginx和fastcgi建立连接的超时时间。fastcgi_read_timeout
。nginx与fastcgi建立连接之后,获得响应的超时时间。若请求需处理的业务逻辑比较复杂,或者在数据里里面查询大量数据,则很可能会在此处超时。返回502 Bad Gateway
fastcgi_send_timeout
。nginx向fastcgi发送请求的超时时间。如果超过这个时间,没有发送完请求,就会断开连接。比如说上传大文件的时候,超时,会返回504 Gateway time-out
上面说到了几个可能会引起502 、504的原因,主要是内存占用过高或者超时。关于内存占用,可以使用free
命令来查看。
下面这张图是centos 7上的free
命令
关于可用内存的计算,centos7 与低版本不一样。
centos 7里面,available只的是 free + buffers/cache - 不可回收的共享部分
。以前available指的是 free + buffers/cache
。
如果看到内存占用高,可以使用top
命令查看当前有多少进程、有多少在运行、内存占用高的进程分布
一般情况下,php源码安装,一般使用--with-config-file-path
设置配置文件的路径,但是源码安装完之后很可能没有php.ini
,需要自己去源码包里面拷贝php.ini-development
或php.ini-production
过来。
上面说到一些php.ini
里面的配置,如果要使用php cli指定某个特定的php.ini
而不是默认的,那么可以使用-c
选项。
举例:
php -c /home/user/nemo/testphp/php.ini index.php