php-fpm彻底解决502(php-fpm多开nginx限制并发定时重启)解决网站卡顿的终极奥义

Posted 杰克文

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php-fpm彻底解决502(php-fpm多开nginx限制并发定时重启)解决网站卡顿的终极奥义相关的知识,希望对你有一定的参考价值。

网站被大量爬虫访问,经常出现访问奇慢的情况,经过不断的探索,终于把php-fpm多开、nginx限制并发、定时重启php-fpm三者结合起来,解决了困扰已久的难题。

第一步、php-fpm多开

要修改三个地方,nginx配置,php配置,/etc/init.d/中增加php-fpm2

nginx里面添加

upstream backend
{
	server 127.0.0.1:9000;
	server 127.0.0.1:9002;
}

转发用tcp协议,不用sock,主要的原因是tcp更稳定,速度差别感觉不到

server中修改

location ~ [^/]\\.php(/|$)
{
    try_files $uri =404;
    fastcgi_pass  backend;
    fastcgi_index index.php;
    include fastcgi.conf;
}

php配置文件复制一份,分别是php-fpm.conf和php-fpm2.conf

位置在php/etc里面

php-fpm.conf

[global]
pid = run/php-fpm.pid
error_log = /root/php.log
log_level = warning

[www]
listen = 	127.0.0.1:9000
listen.backlog = 4096
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
pm = dynamic
pm.max_children = 60
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 10240
request_terminate_timeout = 100
request_slowlog_timeout = 20
slowlog = /root/slow.log

php-fpm2.conf

[global]
pid = run/php-fpm2.pid
error_log = /root/php.log
log_level = warning

[www]
listen = 	127.0.0.1:9002
listen.backlog = 4096
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
pm = dynamic
pm.max_children = 60
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 10240
request_terminate_timeout = 100
request_slowlog_timeout = 20
slowlog = /root/slow.log

重点讲讲

pm = dynamic
pm.max_children = 60
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 10240

由于是开了两个php-fpm,因此开始的时候是10+10=20个进程,最高的时候限制为120个,正常在60个以内是够用的。

max_spare_servers要低于max_children,好处是高并发后会自动降低进程,减少系统开销。

cd /etc/init.d

复制一份php-fpm,名称  php-fpm2     

php-fpm2 全部内容

#! /bin/sh

### BEGIN INIT INFO
# Provides:          php-fpm
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php-fpm
# Description:       starts the PHP FastCGI Process Manager daemon
### END INIT INFO

prefix=/www/server/php/56
exec_prefix=${prefix}

php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm2.conf
php_fpm_PID=${prefix}/var/run/php-fpm2.pid


php_opts="--fpm-config $php_fpm_CONF --pid $php_fpm_PID"


wait_for_pid () {
	try=0

	while test $try -lt 35 ; do

		case "$1" in
			'created')
			if [ -f "$2" ] ; then
				try=''
				break
			fi
			;;

			'removed')
			if [ ! -f "$2" ] ; then
				try=''
				break
			fi
			;;
		esac

		echo -n .
		try=`expr $try + 1`
		sleep 1

	done

}

case "$1" in
	start)
		echo -n "Starting php-fpm "

		$php_fpm_BIN --daemonize $php_opts

		if [ "$?" != 0 ] ; then
			echo " failed"
			exit 1
		fi

		wait_for_pid created $php_fpm_PID

		if [ -n "$try" ] ; then
			echo " failed"
			exit 1
		else
			echo " done"
		fi
	;;

	stop)
		echo -n "Gracefully shutting down php-fpm "

		if [ ! -r $php_fpm_PID ] ; then
			echo "warning, no pid file found - php-fpm is not running ?"
			exit 1
		fi

		kill -QUIT `cat $php_fpm_PID`

		wait_for_pid removed $php_fpm_PID

		if [ -n "$try" ] ; then
			echo " failed. Use force-quit"
			exit 1
		else
			echo " done"
		fi
	;;

	status)
		if [ ! -r $php_fpm_PID ] ; then
			echo "php-fpm is stopped"
			exit 0
		fi

		PID=`cat $php_fpm_PID`
		if ps -p $PID | grep -q $PID; then
			echo "php-fpm (pid $PID) is running..."
		else
			echo "php-fpm dead but pid file exists"
		fi
	;;

	force-quit)
		echo -n "Terminating php-fpm "

		if [ ! -r $php_fpm_PID ] ; then
			echo "warning, no pid file found - php-fpm is not running ?"
			exit 1
		fi

		kill -TERM `cat $php_fpm_PID`

		wait_for_pid removed $php_fpm_PID

		if [ -n "$try" ] ; then
			echo " failed"
			exit 1
		else
			echo " done"
		fi
	;;

	restart)
		$0 stop
		$0 start
	;;

	reload)

		echo -n "Reload service php-fpm "

		if [ ! -r $php_fpm_PID ] ; then
			echo "warning, no pid file found - php-fpm is not running ?"
			exit 1
		fi

		kill -USR2 `cat $php_fpm_PID`

		echo " done"
	;;

	configtest)
		$php_fpm_BIN -t
	;;

	*)
		echo "Usage: $0 {start|stop|force-quit|restart|reload|status|configtest}"
		exit 1
	;;

esac

核心是修改

prefix=/www/server/php/56
exec_prefix=${prefix}

php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm2.conf
php_fpm_PID=${prefix}/var/run/php-fpm2.pid

然后执行

chkconfig --add php-fpm2

设置开机启动

至此,php-fpm双开已经完成。

第二步、限制nginx并发

在nginx的http中添加

limit_conn_zone $binary_remote_addr zone=one:10m;
limit_req_zone $binary_remote_addr zone=two:100m rate=10r/s;

server中添加

limit_conn one 10; 
limit_req zone=two burst=10;

限制单个ip连接数低于10个,并发数10(burst=10),可根据情况修改为20或者30,经测试不带nodelay更稳定。

第三步、定时重启

重启服务

vi /sbin/cq

#/bin/bash
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
/etc/init.d/php-fpm2 restart
/etc/init.d/mysql restart

平滑重启服务

vi /sbin/cq2

#! /bin/sh
getDateTime(){
    date "+%m-%d %H:%M:%S"
}
date=$(getDateTime)
count=$(ps aux | grep -c php-fpm)
echo "$date -- $count" >> /www/jt160/cq.txt

/etc/init.d/php-fpm reload
sleep 1
/etc/init.d/php-fpm2 reload
/etc/init.d/mysql reload

添加执行权限

chmod +x /sbin/*

定时每20秒平滑重启php-fpm,解决php-fpm卡死的问题,经测试,非常好用。

crontab -e

* * * * * /sbin/cq2
* * * * * sleep 20;/sbin/cq2
* * * * * sleep 40;/sbin/cq2

重启的记录保存在 /www/jt160/cq.txt   可以是网站目录,可以随时查看,通常100以内是正常的,php-fpm超过100就是负载太高的时候,一目了然。

重启所有服务输入命令  cq 即可

通过php-fpm多开、nginx限制并发、定时重启php-fpm进程三者结合,网站稳定性上一个大台阶,分享给大家。

如有疑问,欢迎交流。 

定时重启记录如下

以上是关于php-fpm彻底解决502(php-fpm多开nginx限制并发定时重启)解决网站卡顿的终极奥义的主要内容,如果未能解决你的问题,请参考以下文章

Nginx+php-fpm 502 504问题

解决Nginx php-fpm配置有误引起的502错误

Nginx 502 php-fpm 超时问题

Nginx502状态码处理

502 Bad Gateway的可能原因,及解决方法

PHP出现502解决方案