nginx

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > nginx > Nginx代理WebSocket失败

Nginx代理WebSocket失败的完整排查过程

作者:不会写程序的未来程序员

在开发基于 WebSocket 的实时应用时,使用 Nginx 作为反向代理是常见做法,可是我遇见了后端直连 WebSocket 成功,通过 Nginx 代理却失败,本文将完整复盘一次真实排查过程,带你避开所有坑,需要的朋友可以参考下

问题现象

初步怀疑:Nginx 配置错误?

首先检查 Nginx 配置:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream webservers {
    server 192.168.1.10:8080;
}

server {
    listen 80;
    server_name localhost;

    location /ws/ {
        proxy_pass http://webservers/ws/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "$connection_upgrade";  # ⚠️ 这里有坑!
        proxy_read_timeout 3600s;
    }
}

常见错误包括:

但即使修正这些,日志依然为空,说明:请求根本没到 Nginx!

关键转折:前端页面来源被忽略

通过 docker ps 确认端口映射正常:

nginx     0.0.0.0:80->80/tcp

但发现一个致命细节:

前端页面是通过虚拟机 IP 打开的:http://192.168.228.128/
而 WebSocket 地址写的是:ws://localhost/ws/xxx

问题本质

→ 请求压根没发给 Nginx,自然没有日志!

解决方案

方法 1:显式指定虚拟机 IP(临时可用)

// 前端 JS
const ws = new WebSocket('ws://192.168.228.128/ws/xxx');

立即生效!

方法 2:使用相对路径(推荐 ✅)

// 自动继承当前页面的 host
const ws = new WebSocket('/ws/xxx');

优势:

附:正确的 Nginx 配置模板

http {
    # 必须在 http 块顶层!
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream backend {
        server host.docker.internal:8080;  # Docker Desktop 推荐
        # 或 server 192.168.1.10:8080;
    }

    server {
        listen 80;
        server_name _;  # 匹配任意 Host

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }

        location /ws/ {
            access_log /var/log/nginx/ws_access.log;
            proxy_pass http://backend/ws/;
            proxy_http_version 1.1;
            proxy_buffering off;          # 必须关闭
            proxy_cache off;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;  # 无引号!
            proxy_read_timeout 3600s;
        }
    }
}

经验总结

问题类型排查要点
Nginx 无日志先确认请求是否真的发到了 Nginx(检查前端地址、端口映射)
WebSocket 426检查 UpgradeConnection 头是否正确传递
前端连接失败确保 WebSocket 地址与页面同源(避免硬编码 localhost
Docker 环境host.docker.internal 代替 IP 更可靠

最后提醒

localhost 在前端代码中 ≠ 你的服务器!
它永远指向用户浏览器所在的机器

开发时务必注意页面来源与 WebSocket 目标的匹配关系,这是 WebSocket 代理失败的最高频原因

结语

从“426 Upgrade Required”到“连接成功”,看似是配置问题,实则是网络拓扑理解偏差。希望本文能帮你少走弯路!

到此这篇关于Nginx代理WebSocket失败的完整排查过程的文章就介绍到这了,更多相关Nginx代理WebSocket失败内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文