PHP-FPM和Nginx:502 Bad Gateway

80

配置

  • Ubuntu Server 11.10 64位
  • 托管在亚马逊AWS上的Ec2云服务器
  • t1.micro实例

在我写其他内容之前,我想声明一下,我已经查阅了nginx 502 bad gatewayNginx+PHP-FPM 502 Bad Gateway两个线程,但很遗憾这并没有帮助到我。

问题似乎相当普遍:nginx或php-fpm的配置不正确可能会导致502 Bad Gateway错误,而我无法摆脱这个问题。请注意,即使我打开域根目录而没有指定任何特定的目录,这个问题也会出现。

我正在运行一个Amazon EC2 Web服务器,启用了端口9000,开放了端口80等等。

问题具体是,我如何摆脱这个令人讨厌的错误?或者,更好的是,我如何确保php5-fpm真正工作。

我迄今尝试过的事情

主要是对配置文件进行连续的编辑,特别是php-fpm.confnginx.conf

i. php-fpm.conf

我添加了以下内容,但没有太大帮助:

;;;;;;;;;;;;;
; Fpm Start ;
;;;;;;;;;;;;;

;pm.start_servers = 20
;pm.min_spare_servers = 5
;pm.max_spare_servers = 35

现在,随后我尝试包括我的配置文件:

include=/etc/php5/fpm/*.conf

这只会让情况变得更糟。

完整配置

;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix (/usr). This prefix can be dynamicaly changed by using the
; '-p' argument from the command line.

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
; Relative path can also be used. They will be prefixed by:
;  - the global prefix if it's been set (-p arguement)
;  - /usr otherwise
;include=/etc/php5/fpm/*.conf

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Note: the default prefix is /var
; Default Value: none
pid = /var/run/php5-fpm.pid

; Error log file
; Note: the default prefix is /var
; Default Value: log/php-fpm.log
error_log = /var/log/php5-fpm.log

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
log_level = notice

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when 
; a graceful restart will be initiated.  This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
emergency_restart_interval = 0

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
daemonize = no

;;;;;;;;;;;;;
; Fpm Start ;
;;;;;;;;;;;;;

;pm.start_servers = 20
;pm.min_spare_servers = 5
;pm.max_spare_servers = 35

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ; 
;;;;;;;;;;;;;;;;;;;;

; Multiple pools of child processes may be started with different listening
; ports and different management options.  The name of the pool will be
; used in logs and stats. There is no limitation on the number of pools which
; FPM can handle. Your system will tell you anyway :)

; To configure the pools it is recommended to have one .conf file per
; pool in the following directory:
include=/etc/php5/fpm/pool.d/*.conf

ii. nginx.conf

说实话,这份配置是我参考了一些网站后整合而成的。但可以确定的是,在出现502 Bad Gateway错误之前,服务器一直运行良好(没有PHP正常工作)。主要问题在于某些地方出现了严重错误。此时,当我尝试执行service php5-fpm restart命令时,它会卡住,我猜想可能是无限循环之类的问题,而我甚至无法通过CTRL-C退出。

完整配置

user www-data;
worker_processes 1;
pid /var/run/nginx.pid;

events {
    worker_connections 64;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush off;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    server {
        listen 80;
        server_name ec2-xx-xx-xx-xx.compute-x.amazonaws.com;

        location ~ ^(.+\.php)(.*)$ {
            root   /home/wayvac/public;
            fastcgi_pass   unix:/var/run/php5-fpm.pid;  
            #fastcgi_pass   127.0.0.1:9000; #Un-comment this and comment "fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;" if you are not using php-fpm.
            fastcgi_index  index.php;
            set $document_root2 $document_root;
            if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
            if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
            if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
            if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
            if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param   SCRIPT_FILENAME $document_root2$fastcgi_script_name;
            fastcgi_param   PATH_INFO   $fastcgi_path_info;
            fastcgi_param   PATH_TRANSLATED $document_root2$fastcgi_path_info;
            include fastcgi_params;
            fastcgi_param  DOCUMENT_ROOT      $document_root2;
        }       

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        location / {
            root /home/wayvac/public;   
            index index.html index.htm index.php;
        }

        location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
            # Some basic cache-control for static files to be sent to the browser
            expires max;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }

        #include drop.conf;
        #include php.conf;
    }
}
15个回答

152

如果有人因为遇到和我一样的问题而找到了这个页面,我在这里找到了答案。

对于那些不想去点击并自己解决问题的人... ;)

问题:

在Ubuntu或Debian服务器上,NGINX和PHP 5.3可以正常工作,但升级到PHP 5.4会导致502 Bad Gateway错误。查找在端口9000上运行的服务(通常运行netstat -lp或类似命令)返回空白。

解决方法:

打开/etc/php5/fpm/pool.d/www.conf,并记录下“listen”参数(在我的情况下是/var/run/php5-fpm.sock):

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /var/run/php5-fpm.sock

将您的虚拟主机中的fastcgi_pass变量替换为刚才记录的位置。

因此,这是一个来自此处的Symfony2示例配置:

  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  location ~ ^/(app|app_dev)\.php(/|$) {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param  HTTPS              off;
  }

变成这个样子:

  # pass the PHP scripts to FastCGI server at /var/run/php5-fpm.sock
  location ~ ^/(app|app_dev)\.php(/|$) {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param  HTTPS              off;
  }

然后重新启动nginx:

sudo /etc/init.d/nginx restart

注意:如果你不是在SF2上,请将~ ^/(app|app_dev)\.php(/|$) {替换为~ ^/index\.php(/|$) {

希望能为某些人节省一点时间 :)

编辑

当然,你可以在/etc/php5/fpm/pool.d/www.conf中将listen = /var/run/php5-fpm.sock更改为listen = 127.0.0.1:9000,然后重新启动php5-fpm(这样可以避免更改您的虚拟主机),但您必须假设他们更改了php5-fpm以通过套接字而不是监听端口9000的方式运行。

编辑2

如果您仍然遇到502错误,请参阅此答案


2
Unix套接字仅在负载较轻的情况下略快,并且在负载过重时可能会失败。https://drupal.org/node/1635622#comment-6814968 - Desmond Hume
没有帮助,它已经设置成那样了,我一直遇到502错误。 - vsync
网关错误只是意味着Nginx找不到PHP。您确定已安装并运行php-fpm服务吗?如果正在运行,请尝试重新启动它,也许它挂起了。 - nealio82
我遇到了一些问题,需要在Ubuntu 12.04上修复/etc/php5/fpm/pool.d/www.conf文件,但在Debian 7.0上不需要。 - Chu-Siang Lai
1
他们最近似乎进行了更改,使其始终使用原始端口号,即 127.0.0.1:9000 - marksyzm
显示剩余6条评论

29

尝试设置这些值,它可以解决 fast-cgi 中的问题。

fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;

这对我起作用了。由于 nginx 日志中的 fastcgi 错误被截断,因此很难确定。谢谢! - jrhorn424
1
请将它设置为64k,适用于Symfony2.3 :) Symfony的错误输出似乎会超出缓冲区... - Stefan
2
@Jusfeel 这些选项应该添加到nginx的配置文件中。 - biphobe
多么神奇的解决方案。谢谢。 - jan
我申请了在nginx下安装的Siwapp,它运行得非常好!非常感谢 :) - akajack

11

我进行了各种类似的调整,但是偶尔会出现501/502错误(每天一次)。

这是我在/etc/php5/fpm/pool.d/www.conf上的设置,以避免501和502 nginx错误... 服务器有16GB RAM。这个配置适用于8GB RAM服务器...

sudo nano /etc/php5/fpm/pool.d/www.conf

然后设置以下值:

pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 500

更改后请重新启动php-fpm

sudo service php-fpm restart

4
如果像我一样在升级php-fpm之后遇到了问题,请尝试以下方法: 打开/etc/php5/fpm/pool.d/www.conf文件 取消以下行的注释:
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

然后重启php-fpm。


对我也解决了。在Arch Linux上,conf文件是/etc/php/php-fpm.d/www/conf。请注意,将权限设置为0666可能不适用于生产环境。相反,生产服务器应该匹配Nginx用户和PHP-FPM用户,并保持权限为0660以增加安全性。 - conradkleinespel

3

请不要忘记php-fpm是一个服务。在安装完成后,请确保启动它:

# service php-fpm start
# chkconfig php-fpm on

2

对于其他遇到类似问题的人,我也尝试了调整超时时间,因为我不想停止使用Unix套接字...经过长时间的故障排除和很少的线索,我发现这个问题是由我几个月前在php-fpm中启用的APC扩展引起的。禁用此扩展程序解决了间歇性的502错误,最简单的方法是注释掉以下行:

;extension = apc.so

这对我起了作用!

2

您应该查看错误日志。 默认情况下,其位置在/var/log/nginx/error.log

在我的情况下,502错误是因为:

GET /app_dev.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "symfony2.local"
2016/05/25 11:57:28 [error] 22889#22889: *3 upstream sent too big header while reading response header from upstream, client: 127.0.0.1, server: symfony2.local, request: "GET /app_dev.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "symfony2.local"
2016/05/25 11:57:29 [error] 22889#22889: *3 upstream sent too big header while reading response header from upstream, client: 127.0.0.1, server: symfony2.local, request: "GET /app_dev.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "symfony2.local"
2016/05/25 11:57:29 [error] 22889#22889: *3 upstream sent too big header while reading response header from upstream, client: 127.0.0.1, server: symfony2.local, request: "GET /app_dev.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "symfony2.local"

当我们确切知道出了什么问题,就可以修复它。对于这些错误,只需修改缓冲区:

fastcgi_buffers 16 512k; 
fastcgi_buffer_size 512k;

1
希望这个提示能够拯救其他人的生命。在我的情况下,问题是我没有足够的内存,但只是稍微不足,很难想到这一点。在这上面浪费了3小时。我建议运行以下代码:
sudo htop

或者

sudo free -m

如果你的内存不足,需要在服务器上运行有问题的请求,以查看内存是否耗尽。如果像我这样出现了这种情况,你需要创建交换文件(除非你已经有一个)。

我按照这个教程在Ubuntu Server 14.04上创建了交换文件,效果很好: http://www.cyberciti.biz/faq/ubuntu-linux-create-add-swap-file/


1
端口在5.4中更改为9001,只需在nginx配置文件和php-fpm配置文件中将端口从9000更改为9001即可。

0

在修改Nginx配置之前,先尝试禁用ChromePHP。

1 - 打开app/config/config_dev.yml文件

2 - 注释掉以下这些行:

chromephp:
    type:   chromephp
    level:  info

ChromePHP将调试信息json编码打包在X-ChromePhp-Data头中,这对于带有fastcgi的nginx默认配置来说太大了。


来源: [1] https://github.com/symfony/symfony/issues/8413#issuecomment-20412848 [2] https://dev59.com/sGMm5IYBdhLWcg3wT9qU#18250782 - Lucas Bustamante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接