阅读 2180
深挖502和504

深挖502和504

引言

平时我们访问网站,或者在工作中请求一些接口,或者线上服务报警,经常会看见502和504这两个状态码。如果是运维同学收到502或504的问题反馈,通常第一件事就是重启服务,往往就好了,重启大法无敌,哈哈哈。本文就了解一下什么情况下会出现这两种状态码以及这遇到这两种状态码的情况下如何解决

502和504的含义

502 Bad Gateway

字面意思就是网关错误。比较官方的说法是,作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应

504 Gateway Time-out

字面意思是网关超时。官方说法,作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应

上边的解释都比较的抽象,下边通过具体实例来说明导致这两种状态的原因,从而深入理解这两个状态码的含义

导致502和504的原因

502 Bad Gateway

首先,我们都知道5开头的状态码为服务器端为问题。生活中我们会遇见这样的情况,我们在春节抢票的时候,发现出现了502,或者某个明星上热搜,某博出现了502的情况。通俗点来说,这个其实就是因为网站突然一下子有大量的请求进来,对方的服务器无法及时处理,就导致了502

那从专业上来说,当网页上有一个请求过来,nginx将请求交给php-fpm去处理,这个时候由于某些原因,请求还没执行完毕,处理这个请求的进程终止了

这种情况其实是和php-fpm的配置有关的,主要注意下边三个配置:

php.ini中的max_execution_time
This sets the maximum time in seconds a script is allowed to run before it is terminated by the parser. This helps prevent poorly written scripts from tying up the server. The default setting is 30. When running PHP from the command line the default setting is 0.

官方文档:https://www.php.net/manual/en/info.configuration.php#ini.max-execution-time
复制代码

上边的意思大概是,这个参数设置了允许脚本在解析器终止之前运行的最长时间(以秒为单位)。这有助于防止编写不正确的脚本占用服务器资源,默认设置为30。从命令行运行PHP时,默认设置为0。所以当请求超过30s没有结果,就被终止了,我们就会收到502的错误

php-fpm.conf中的request_terminate_timeout
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
复制代码

上边是php-fpm.conf配置文件中,该配置的注释,大致意思是: request_terminate_timeout适用于,当max_execution_time由于某种原因无法终止脚本的时候,php-fpm会把这个请求干掉

php-fpm.conf中的max_children

这个配置的含义在之前的文章中也有解释(全面了解CGI、FastCGI、PHP-FPM),它表示可以同时存活的子进程的最大数量。当在一个时间段内有大量的请求进来,导致达到了php-fpm最大响应数量,那么后续的请求就会出现502的情况。这里可以使用下边这个命令查看当前的连接数

#netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

返回结果示例: 
LAST_ACK 5   (正在等待处理的请求数) 
SYN_RECV 30 
ESTABLISHED 1597 (正常数据传输状态) 
FIN_WAIT1 51 
FIN_WAIT2 504 
TIME_WAIT 1057 (处理完毕,等待超时结束的请求数) 

状态:描述 
CLOSED:无连接是活动的或正在进行 
LISTEN:服务器在等待进入呼叫 
SYN_RECV:一个连接请求已经到达,等待确认 
SYN_SENT:应用已经开始,打开一个连接 
ESTABLISHED:正常数据传输状态 
FIN_WAIT1:应用说它已经完成 
FIN_WAIT2:另一边已同意释放 
ITMED_WAIT:等待所有分组死掉 
CLOSING:两边同时尝试关闭 
TIME_WAIT:另一边已初始化一个释放 
LAST_ACK:等待所有分组死掉

来自:https://www.cnblogs.com/linyouyi/p/10108440.html
复制代码

上边我们说到,一遇到这种情况,运维同学做的事情就是重启,当重启php-fpm之后,php-fpm会释放资源,但是不到三分钟,发现又出现了502的情况,这种情况下,一般需要查看一下数据库是否有大量的locked的进程,也就是数据库死锁导致超时,此时需要重启数据库或者杀死死锁的SQL进程

504 Gateway Time-out

504一般都是和nginx的配置有关。比如nginx设置了超时时间,当在超时时间内,nginx没有收到php-fpm的响应,它就会给客户端返回504。当fastcgi的缓冲区太小,导致fastcgi进程被挂起,也会演变成504错误

主要涉及到nginx中的一下几个配置参数:

fastcgi_connect_timeout
含义:定义用于与FastCGI服务器建立连接的超时时间

fastcgi_send_timeout
含义:设置将请求传输到FastCGI服务器的超时时间。 超时仅在两个连续的写操作之间设置,而不用于整个请求的传输。 如果FastCGI服务器在此时间内未收到任何信息,则连接将关闭

fastcgi_read_timeout
含义:定义用于从FastCGI服务器读取响应的超时时间。 超时仅在两次连续的读取操作之间设置,而不用于传输整个响应。 如果FastCGI服务器在此时间内未传输任何内容,则连接将关闭

fastcgi_buffer_size
含义:设置size用于读取从FastCGI服务器接收到的响应的第一部分的缓冲区。这部分通常包含一个小的响应头。默认情况下,缓冲区大小等于一个内存页

fastcgi_buffers
含义:为单个连接设置用于从FastCGI服务器读取响应的缓冲区的number和size。默认情况下,缓冲区大小等于一个内存页

fastcgi_busy_buffers_size
含义:当缓冲中启用了从FastCGI的服务器响应,限制总size的缓冲区,可以是正忙于发送到客户端的响应,而响应尚不充分阅读。同时,其余的缓冲区可用于读取响应,并在需要时将响应的一部分缓冲到临时文件中。默认情况下,size受限于fastcgi_buffer_size和fastcgi_buffers指令设置的两个缓冲区的大小 

fastcgi_temp_file_write_size
fastcgi_intercept_errors

以上大家可参考官方文档:http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html
复制代码
文章分类
后端
文章标签