无法通过 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;
}
}
}
我正在使用 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;
}
}
}