无法通过 VM 内的 Nginx 代理到 Websocket

Unable to Proxy to Websocket via Nginx inside a VM

我正在使用 nginx 和 django 频道。 Django 应用程序有一个 Http 连接和一个 WebSocket 连接。下图显示了三种情况及其工作原理。

情况 1 - 一切都在本地设置,客户端可以发送 http 请求并创建到 django 应用程序的 websocket 连接。

情况 2 - 在 VM 上仅设置了 django 应用程序,客户端可以发送 http 请求并创建到 django 应用程序的 websocket 连接。

情况 3 - 一切都在 VM (VirtualBox) 中设置,客户端可以发送 http 请求并且无法创建到 django 应用程序的 websocket 连接。对于 websocket 连接尝试,django 应用程序响应 404 错误。

这是 nginx 配置

注意:Django 应用 运行 在 docker 容器中,称为 'backend'。

worker_processes 1;

events { worker_connections 1024; }

http {

    upstream backend {
        server backend:8000;
    }

    server {
        listen 80;

        location /backend/ {
            proxy_pass         http://backend;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
        }

        location /static/ {
            proxy_pass http://backend/static;
        }
    }
}

django 应用程序的日志显示 http 请求成功。然后在 websocket 端点失败的 GET 请求。

WARNING Not Found: /backend/ws/processor

"GET /backend/ws/processor/" 404 3127

所以看起来 nginx 正在重定向请求,但它没有根据配置升级到 websocket 连接。在相同的设置条件下,配置确实在本地工作。但是,我可以从客户端通过 VM 直接连接到 django 应用程序(情况 2)。

代理在本地工作,并且在 VM 内正确重定向 http 连接。 8000和80端口都在VM上转发了

这导致我认为nginx配置不正确无法升级对web socket连接的请求。

添加 proxy_http_version 似乎可以解决此问题。

worker_processes 1;

events { worker_connections 1024; }

http {

    upstream backend {
        server backend:8000;
    }

    server {
        listen 80;

        location /backend/ {
            proxy_pass         http://backend;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_http_version 1.1;   <===== ADD THIS LINE
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
        }

        location /static/ {
            proxy_pass http://backend/static;
        }
    }
}