【问题标题】:Nginx 502 Bad Gateway error when using proxy使用代理时 Nginx 502 Bad Gateway 错误
【发布时间】:2018-05-23 21:07:54
【问题描述】:

我有一个 Angular 构建和一个 Laravel 后端,提供在一台服务器上运行的 API。我已经在 nginx 中配置了它们,前端有一个后端服务器的代理。

后端在 url(例如占位符)http://api.example.com 上运行,前端在 http://example.com 上运行

前端配置:

server {
    listen       80;
    server_name  example.com;

    location /api {
        proxy_pass http://api.example.com;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location / {
        root  /var/www/angular/em-frontend/dist;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html$is_args$args;
    }
}

后端配置:

server {
        listen 80;
        server_name api.example.com;

        root /var/www/angular/em-backend/public;

        index index.php index.html index.htm;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.php?$query_string;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }
}

现在,当我从前端进行任何 api 调用时,我从 nginx 收到 502 Bad Gateway 错误。

来自 nginx 错误日志:

2017/12/09 23:30:40 [alert] 5932#5932: 768 worker_connections are not enough
2017/12/09 23:30:40 [error] 5932#5932: *770 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: IP_MASKED, server: example.com, request: "GET /api/endpoint HTTP/1.1", upstream: "http://IP_ADDRESS:80/api/endpoint", host: "example.com", referrer: "http://example.com/dashboard"

知道如何解决这个问题吗?

【问题讨论】:

  • 这些是在同一个 nginx 上运行还是在不同的 nginx 上运行?您是否还在主机文件中为api.example.com 输入了条目?你也在使用 websockets 吗?如果是,那是哪条路?
  • 建立在 Tarun 可能领先的位置上,太多工人的错误可能表明前端代理的循环,如果主机名配置不正确,它可能会向自身发送请求。但是对等点重置的连接是不同的,并且可能是服务器端代码执行中的合法错误。你有来自每个 nginx 实例的日志吗,php 引擎呢?直接调用后端有效吗?

标签: ubuntu nginx proxy


【解决方案1】:

你必须像这个例子一样在 location 块中使用 proxy-pass:

upstream myproject {
   server ip1 ;
   server ip2 ;
   server ip3 ;

} 
location / { 
   proxy_pass      http://myproject;
}

【讨论】:

  • 这是针对哪个配置,后端还是前端?多个ip有什么用?你能把它写在我的配置文件中吗?
  • Downvote:Proxy_pass 在前端配置,您的示例添加了 OP 可能不需要的负载平衡。后端使用 CGI 作为 PHP,不需要 proxy_pass。
【解决方案2】:

我相信您的问题是主机名配置创建了一个递归循环,其中一个请求被代理回前端,很快就会耗尽所有工作人员。您将通过对前端的单个请求在访问日志中生成许多条目来识别这一点。

我能够使用您提供的配置快速重现该错误。下面是一个修改后的版本,它消除了在后端服务器上提供 2 个不同静态文件的配置,以说明所需的最低配置。如果可行,您可以重新添加 cgi_pass 配置。

#set api domain to use alternate port, could also just tack onto proxy_pass.
upstream api.example.com {
    server localhost:8081;
}

#frontend listening on port 8080
server {
    listen       8080;
    server_name  example.com;

    location /api {
        proxy_pass http://api.example.com;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location / {
        root  /usr/local/var/www;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html$is_args$args;
    }
}

#backend listening on 8081
server {
        listen 8081;
        server_name api.example.com;

        index index.php index.html index.htm;

        location / {  # will match any url not ending in .php
              root  /usr/local/var/www;
              try_files $uri $uri/ /index.html;
        }
        location ~ \.php { #successfully responds to http://example.com:8080/api/*.php
              root  /usr/local/var/www;
              try_files $uri $uri/ /service.html;
        }
}

【讨论】:

  • 嗨,埃迪,感谢您的详细回复。一旦我有时间,我会试试这个。不过还是非常感谢!
  • 嗨 Eddie,我刚刚试了一下,使用此配置我无法访问 url。当我浏览到 example.com 或 api.example.com 时,我得到一个 ERR_CONNECTION_REFUSED。但是,如果将端口放在它后面,例如 example.com:8080 或 api.example.com:8081,它确实可以工作。知道如何解决这个问题吗?
  • 对不起,我在本地使用 8080,因为我以非 root 身份运行 nginx。默认情况下 api.example.com 将是端口 80,或端口 443 用于 https。只需将前端监听的端口更改为 80,就可以让后端与前端知道使用该端口相同。
【解决方案3】:

我遇到了类似的问题,解决了:

events {
    worker_connections 1024;
}

events 块与http 块处于同一级别。

【讨论】:

    猜你喜欢
    • 2018-04-23
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 2017-12-30
    相关资源
    最近更新 更多