iSt0ne's Notes

解决NGINX 502 Bad Gateway错误

今天遇到Nginx 502错误,在网上找了些资料,拼凑成此文。

出现NGINX 502 Bad Gateway错误可按如下顺序排查:

  1. FastCGI进程是否已经启动

  2. FastCGI worker进程数是否不够
    运行netstat -anpo | grep “php-fpm” |wc -l判断是否接近FastCGI进程,接近配置文件中设置的数值,表明worker进程数设置太少

  3. FastCGI执行时间过长
    根据实际情况调高以下参数值,同时调高 request_terminate_timeout值,如果得到改善,可能是脚本程序执行时间太长所致,可以对脚本进行优化来彻底解决问题。
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;

  1. FastCGI Buffer不够
    nginx和apache一样,有前端缓冲限制,可以调整缓冲参数(后面有详细解释)
    fastcgi_buffer_size 32k;
    fastcgi_buffers 8 32k;

  2. Proxy Buffer不够
    如果你用了Proxy,调整
    proxy_buffer_size 16k;
    proxy_buffers 4 16k;

  3. https转发配置错误

FastCGI buffer的配置导致502 Bad Gateway:

Nginx 的 buffer 机制:来自 FastCGI Server 的响应,Nginx 将其缓冲到内存中,然后依次发送到客户端浏览器。缓冲区的大小涉及的两个参数是fastcgi_buffers 和 fastcgi_buffer_size 。可以参考FastCGI配置文档
fastcgi_buffer_size:指定将用多大的缓冲区来读取从FastCGI进程到来应答头。
fastcgi_buffers:指定了从FastCGI进程到来的应答,本地将用多少和多大的缓冲区读取。

如果:
fastcgi_buffer_size 16k;
fastcgi_buffers 16 16k;

那么:
fastcgi_buffer=16*16+16=272k

如果一个php脚本产生的页面大小为32k,将分2个16k去缓存页面,如果一个php脚本所产生的页面大小为256k,则会为其分配16个16k的缓冲区来缓存,如果大于256k,大于256k的部分会缓存到fastcgi_temp指定的路径中,同时你会在 error.log 中看到一条类似 warning。如果想关闭对所有请求道磁盘的缓冲,可以将fastcgi_max_temp_file_size 设置为0。通常这个值的设置应该选择一个你的站点中的php脚本所产生的页面大小的中间值。如果您服务器上的内存够大,可以将以上参数适当调大。当然以上参数并不是越大越好,需要根据您的实际情况,如页面大小及服务器内存大小,如果以上参数太小的话,就会频繁的往磁盘写数据,对性能影响还是很大的。可以一步步调整参数,直到没有这个warning信息。

以下为配置实例:

1
2
3
4
5
6
7
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

fastcgi_buffers 16 16k; 默认配置fastcgi_buffers 8 4k|8k;根据默认的内存页大小分配4k或8k,我们是设置16个16k的buffer呢还是设置成4个64k呢?当设置成64k或者更大时可能会浪费大量内存,如果有一个65k的网页,要占用128k的内存。如果我们想让更多的内容缓存在内存中,就要吧每个buffer分的尽量小。哪是否越小越好,也不是,如果设置的很小,会加重内存管理程序的负担。fastcgi_buffer_size设置的过小,当herder过大是也会报502错误。

下面程序可以获得默认的内存页大小(x86_64位Linux系统默认内存页大小是4KB):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@d13030326 ~]# uname -a
Linux d13030326 2.6.32-220.13.1.el6.x86_64 #1 SMP Tue Apr 17 23:56:34 BST 2012 x86_64 x86_64 x86_64 GNU/Linux
[root@d13030326 ~]# cat pagesize.c
#include <stdio.h>
#include <unistd.h>
int
main(void)
{
printf("page size = %d Byte\n", getpagesize());
return 0;
}
[root@d13030326 ~]# gcc pagesize.c
[root@d13030326 ~]# ./a.out
page size = 4096 Byte