打印

[轉]Nginx提示502和504错误的终极解决方案

[轉]Nginx提示502和504错误的终极解决方案

一、错误提示说明:
Nginx 502 Bad Gateway的含义是请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致PHP-CGI进程终止。
Nginx 504 Gateway Time-out的含义是所请求的网关没有请求到,简单来说就是没有请求到可以执行的PHP-CGI。
二、错误提示原因分析:
解决这两个问题其实是需要综合思考的,一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关,
而Nginx 504 Gateway Time-out则是与nginx.conf的设置有关。
php-fpm.conf有两个至关重要的参数,一个是”max_children”,另一个是”request_terminate_timeout” ,但是这个值不是通用的,而是需要自己计算的。


计算的方式如下:
如果你的服务器性能足够好,且宽带资源足够充足,PHP脚本没有系循环或BUG的话你可以直接将”request_terminate_timeout”设置成0s。0s的含义是让PHP-CGI一直执行下去而没有时间限制。而如果你做不到这一点,也就是说你的PHP-CGI可能出现某个BUG,或者你的宽带不够充足或者其他的原因导致你的PHP-CGI能够假死那么就建议你给”request_terminate_timeout”赋一个值,这个值可以根据你服务器的性能进行设定。一般来说性能越好你可以设置越高,20分钟-30分钟都可以。由于我的服务器PHP脚本需要长时间运行,有的可能会超过10分钟因此我设置了900秒,这样不会导致PHP-CGI死掉而出现502 Bad gateway这个错误。
而”max_children”这个值又是怎么计算出来的呢?这个值原则上是越大越好,php-cgi的进程多了就会处理的很快,排队的请求就会很少。设置”max_children”也需要根据服务器的性能进行设定,一般来说一台服务器正常情况下每一个php-cgi所耗费的内存在20M左右,因此我的”max_children”我设置成40个,20M*40=800M也就是说在峰值的时候所有PHP-CGI所耗内存在800M以内,低于我的有效内存1Gb。而如果我的”max_children”设置的较小,比如5-10个,那么php-cgi就会“很累”,处理速度也很慢,等待的时间也较长。如果长时间没有得到处理的请求就会出现504 Gateway Time-out这个错误,而正在处理的很累的那几个php-cgi如果遇到了问题就会出现502 Bad gateway这个错误。
三、临时解决办法:
综上所述,Nginx提示502和504错误的临时解决办法是:
1、调整php-fpm.conf的相关设置:
<value name=”max_children”>32</value>
<value name=”request_terminate_timeout”>30s</value>
2、调整nginx.conf的相关设置:
fastcgi_connect_timeout 600;
fastcgi_send_timeout 600;
fastcgi_read_timeout 600;
fastcgi_buffer_size 256k;
fastcgi_buffers 16 256k;
fastcgi_busy_buffers_size 512k;
fastcgi_temp_file_write_size 512k;
四、终级解决方案:
标题3中所示的解决方案只能临时解决问题,而如果网站的访问量确实非常非常大,而Nginx+FastCGI只能对处理瞬间或短时间内的高并发有很好的效果,所以目前唯一的终极解决方案是:定时平滑重启php-cgi。
具体配置如下:
1、写一个非常简单的脚本:
#vi /home/www/scripts/php-fpm.sh
内容如下:
#!/bin/bash
# This script run at */1
/usr/local/php/sbin/php-fpm reload
2、将脚本添加至计划任务:
#crontab -e
内容如下:
*/1 * * * * /home/www/scripts/php-fpm.sh
注:为了省事起见,也可以不写脚本,直接在crontab里写入php-fpm的平滑重启命令。
原创文章,转载请注明:
转载自:韦少乾[赵丙良] – 服务器系统架构

本帖最近评分记录
  • licess 威望 +6 2010-12-6 17:06

TOP

回复 1# 的帖子

我按照你的“标题3中所示的解决方案”做了以后,两天没有死机了(ps.以前每天死机一次,都是提示502和504错误)。
但是我在使用“四、终级解决方案:”时遇到了问题:
1.输入crontab -e,提示command not found.  这是怎么回事?怎么办?
2.手动执行 /root/lnmp restart之后网站可以访问的,但是邮件发不出去
我发现我执行了以下脚本之后,只要重启lnmp,sendmail就不能用了,高手帮忙看一下怎么回事?怎么办?
============================================================
#!/bin/bash
#########################################################################
#
# File:         autosafe.sh
# Description:  
# Language:     GNU Bourne-Again SHell
# Version:        1.1
# Date:                2010-6-23
# Corp.:        c1gstudio.com
# Author:        c1g
# WWW:                http://blog.c1gstudio.com
### END INIT INFO
###############################################################################

V_DELUSER="adm lp sync shutdown halt mail news uucp operator games gopher ftp"
V_DELGROUP="adm lp mail news uucp games gopher mailnull floppy dip pppusers popusers slipusers daemon"
V_PASSMINLEN=8
V_HISTSIZE=30
V_TMOUT=300
V_GROUPNAME=suadmin
V_SERVICE="acpid anacron apmd atd auditd autofs avahi-daemon avahi-dnsconfd bluetooth cpuspeed cups dhcpd firstboot gpm haldaemon hidd ip6tables ipsec isdn kudzu lpd mcstrans messagebus microcode_ctl netfs nfs nfslock nscd pcscd portmap readahead_early restorecond rpcgssd rpcidmapd rstatd sendmail setroubleshoot snmpd sysstat xfs xinetd yppasswdd ypserv yum-updatesd"
V_TTY="3|4|5|6"
V_SUID=(
        '/usr/bin/chage'
        '/usr/bin/gpasswd'
        '/usr/bin/wall'
        '/usr/bin/chfn'
        '/usr/bin/chsh'
        '/usr/bin/newgrp'
        '/usr/bin/write'
        '/usr/sbin/usernetctl'
        '/bin/traceroute'
        '/bin/mount'
        '/bin/umount'
        '/sbin/netreport'
)
version=1.0


# we need root to run
if test "`id -u`" -ne 0
then
        echo "You need to start as root!"
        exit
fi

case $1 in
        "deluser")
                 echo "delete user ..."
                 for i in $V_DELUSER ;do
                 echo "deleting $i";
                 userdel $i ;
                 done
                ;;

        "delgroup")
                 echo "delete group ..."
                 for i in $V_DELGROUP ;do
                 echo "deleting $i";
                 groupdel $i;
                 done
                ;;

        "password")
                 echo "change password limit ..."
                 echo "/etc/login.defs"
                 echo "PASS_MIN_LEN $V_PASSMINLEN"
                 sed -i "/^PASS_MIN_LEN/s/5/$V_PASSMINLEN/" /etc/login.defs
                ;;

        "history")
                 echo "change history limit ..."
                 echo "/etc/profile"
                 echo "HISTSIZE $V_HISTSIZE"
                 sed -i "/^HISTSIZE/s/1000/$V_HISTSIZE/" /etc/profile
                ;;

        "logintimeout")
                 echo "change login timeout ..."
                 echo "/etc/profile"
                 echo "TMOUT=$V_TMOUT"
                 sed -i "/^HISTSIZE/a\TMOUT=$V_TMOUT" /etc/profile
                ;;

        "bashhistory")
                echo "denied bashhistory ..."
                echo "/etc/skel/.bash_logout"
                echo 'rm -f $HOME/.bash_history'
                if egrep "bash_history" /etc/skel/.bash_logout > /dev/null
                then
                        echo 'warning:existed'
                else
                 echo 'rm -f $HOME/.bash_history' >> /etc/skel/.bash_logout
                fi

                ;;
        "addgroup")
                echo "groupadd $V_GROUPNAME ..."
                groupadd $V_GROUPNAME
                ;;

        "sugroup")
                echo "permit $V_GROUPNAME use su ..."
                echo "/etc/pam.d/su"
                echo "auth sufficient /lib/security/pam_rootok.so debug"
                echo "auth required /lib/security/pam_wheel.so group=$V_GROUPNAME"
                if egrep "auth sufficient /lib/security/pam_rootok.so debug" /etc/pam.d/su > /dev/null
                then
                        echo 'warning:existed'
                else
                        echo 'auth sufficient /lib/security/pam_rootok.so debug' >> /etc/pam.d/su
                        echo "auth required /lib/security/pam_wheel.so group=${V_GROUPNAME}" >> /etc/pam.d/su
                fi
                ;;

        "denyrootssh")
                echo "denied root login ..."
                echo "/etc/ssh/sshd_config"
                echo "PermitRootLogin no"
                sed -i '/^#PermitRootLogin/s/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
                ;;

        "stopservice")
                echo "stop services ..."
                        for i in $V_SERVICE ;do
                        service $i stop;
                        done
                ;;

        "closeservice")
                echo "close services autostart ..."
                        for i in $V_SERVICE ;do
                        chkconfig $i off;
                        done
                ;;

        "tty")
                echo "close tty ..."
                echo "/etc/inittab"
                echo "#3:2345:respawn:/sbin/mingetty tty3"
                echo "#4:2345:respawn:/sbin/mingetty tty4"
                echo "#5:2345:respawn:/sbin/mingetty tty5"
                echo "#6:2345:respawn:/sbin/mingetty tty6"
                sed -i '/^[$V_TTY]:2345/s/^/#/' /etc/inittab
                ;;

        "ctrlaltdel")
                echo "close ctrl+alt+del to restart server ..."
                echo "/etc/inittab"
                echo "#ca::ctrlaltdel:/sbin/shutdown -t3 -r now"
                sed -i '/^ca::/s/^/#/' /etc/inittab
                ;;

        "lockfile")
                echo "lock user&services ..."
                echo "chattr +i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/services"
                chattr +i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/services
                ;;

        "unlockfile")
                echo "unlock user&services ..."
                echo "chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/services"
                chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/services
                ;;

        "chmodinit")
                echo "init script only for root ..."
                echo "chmod -R 700 /etc/init.d/*"
                echo "chmod 600 /etc/grub.conf"
                echo "chattr +i /etc/grub.conf"
                chmod -R 700 /etc/init.d/*
                chmod 600 /etc/grub.conf
                chattr +i /etc/grub.conf
                ;;

        "chmodcommand")
                echo "remove SUID ..."
                echo "/usr/bin/chage /usr/bin/gpasswd ..."
                for i in ${V_SUID[@]};
                do
                        chmod a-s $i
                done
                ;;

        "version")
                echo "Version: Autosafe for Linux $version"
                ;;

        *)       
                echo "Usage: $0 <action>"
                echo ""
                echo "        deluser      delete user"
                echo "        delgroup     delete group"
                echo "        password     change password limit"
                echo "        history      change history limit"
                echo "        logintimeout      change login timeout"
                echo "        bashhistory      denied bashhistory"
                echo "        addgroup      groupadd $V_GROUPNAME"
                echo "        sugroup      permit $V_GROUPNAME use su"
                echo "        denyrootssh      denied root login"
                echo "        stopservice     stop services "
                echo "        closeservice      close services"
                echo "        tty      close tty"
                echo "        ctrlaltdel     close ctrl+alt+del"
                echo "        lockfile      lock user&services"
                echo "        unlockfile      unlock user&services"
                echo "        chmodinit      init script only for root"
                echo "        chmodcommand      remove SUID"
                echo "        version      "
                echo ""

                ;;
esac
======================================================================================

TOP