惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
雷峰网
雷峰网
S
SegmentFault 最新的问题
量子位
有赞技术团队
有赞技术团队
V
V2EX
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Jina AI
Jina AI
C
Check Point Blog
G
Google Developers Blog
博客园 - 叶小钗
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
T
Tailwind CSS Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
U
Unit 42

CHEGVA

达梦集群高可用连接配置 PostgreSQL 集群异常恢复 高效沟通(五):好老板要善于提问 K8s etcd 集群崩溃异常恢复 周易雅说精品课答疑讲座 庄子四重人格境界与易经哲理 《旧梦》 《庄子·齐物论》哲学解读与批判 第一次评上三好学生 真行啊阿根廷🇦🇷 达梦数据库备份恢复操作指南 | CHEGVA 十二经脉,子午流注走向图 | CHEGVA 中医阴阳、藏象核心概念解析 | CHEGVA 深入理解CAP理论 | CHEGVA 多路径磁盘使用场景 | CHEGVA vLLM集成Ray分布式推理部署模型实战 | CHEGVA 达梦数据库备份详解 | CHEGVA 大模型 Temperature 与 Top_p/Top_k 参数详解
Spring Cloud Gateway 和 Nginx 网关代理 WebSocket 路由配置
anzhihe · 2026-08-16 · via CHEGVA

最近有个小程序项目客户在并网时有个需求:需要在他们的Spring Cloud Gateway 公网网关开个入口,打到自建的Nginx代理转发到后端服务,需要同时能支持 http 和 ws 的请求。整体访问链路从公网 → Spring Cloud Gateway → Nginx → 应用服务主要的工作是Spring Cloud Gateway 和 Nginx 的路由配置和整个链路的联调,mark一下。

spring:
  cloud:
    gateway:
      routes:
        # 1. WebSocket 路由:处理 WebSocket 握手请求
        - id: websocket_route
          uri: wss://your-backend-service # 非加密的 WebSocket 协议使用 ws://
          predicates:
            # 匹配 /ws/ 路径及其子路径,并确保包含 Upgrade 头
            - Path=/ws/**
            - Header=Upgrade, websocket
          filters:
            # 不要用 StripPrefix,会破坏 WebSocket 握手头
            - name: SetResponseHeader
              args:
                name: Sec-WebSocket-Accept
                value: ".*"  # 让后端自行生成
            # 保持 Host 头不变
            - name: PreserveHostHeader

        # 2. HTTP 路由:处理普通的 HTTP 请求处理(处理非 WebSocket 请求)
        - id: http_route
          # 普通的 HTTP 负载均衡
          uri: lb://your-backend-service
          predicates:
            # 匹配相同的路径
            - Path=/ws/**
          filters:
            # 显式保证查询参数透传
            - StripPrefix=0

      # 全局 CORS 配置(可选)
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "*"
            allowed-methods: "*"
            allowed-headers: "*"
            allow-credentials: true

二、Nginx 配置(第二层)

http {
    # 定义 connection_upgrade 变量
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    upstream app_cluster {
        server 127.0.0.1:8080;
        # 可添加多个 app 实例
    }

        # ---------- HTTP 服务器(提供 ws://)----------
    server {
        listen 80;
        server_name test.com.cn;   # 内网域名或 IP

        location /ws/ {
            # 去掉 /ws/ 前缀,将请求转发到后端根路径
            proxy_pass http://app_cluster/;

            # 必须的 WebSocket 握手配置
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 传递原始 Host 和客户端 IP
            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_read_timeout 3600s;
            proxy_send_timeout 3600s;
            proxy_buffering off;
        }
        
        # 其他非 /ws/ 请求
        location / {
            proxy_pass http://app_cluster;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    
    # ---------- HTTPS 服务器(提供 wss://)----------
    server {
        listen 443 ssl;
        server_name test.com.cn;

        # 网关自身的 SSL 证书(客户端信任的证书)
        ssl_certificate     /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        location /ws/ {
            proxy_pass http://app_cluster/; # 注意末尾斜杠,可去掉 /ws/ 前缀,不加末尾"/" 会保留 /ws/ 前缀 

            # 关键:WebSocket 握手依赖 HTTP/1.1
            proxy_http_version 1.1;

            # 传递 WebSocket 升级头
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

            # 传递原始信息
            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 X-Forwarded-Proto $scheme; # 告诉后端客户端实际使用的是 HTTPS(当后端需要区分协议时有用)

            # 长连接超时(避免空闲断开)
            proxy_read_timeout 3600s;
            proxy_send_timeout 3600s;
            # 关闭缓冲,提升实时性
            proxy_buffering off;
        }

        # 其他非 /ws/ 请求
        location / {
            proxy_pass http://app_cluster;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

后端为 HTTPS(WSS,加密)的情况

如果后端 WebSocket 服务器也要求使用 WSS(例如 https://backend_server:8443),则需额外处理 SSL 验证:

location /ws/ {
    proxy_pass https://backend_server:8443/;   # 使用 HTTPS 协议

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    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 X-Forwarded-Proto $scheme;

    # 如果后端使用自签名证书,关闭 SSL 验证(测试环境)
    proxy_ssl_verify off;
    # 或者指定 CA 证书链:proxy_ssl_trusted_certificate /path/to/ca.pem;

    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
    proxy_buffering off;
}

# 强制将 HTTP 重定向到 HTTPS(可选配置)
server {
    listen 80;
    server_name test.com.cn;
    return 301 https://$host$request_uri;
}

关键检查项

  • 确认 proxy_pass 的 URL 正确:如果你想去掉 /ws/ 前缀,proxy_pass 末尾要带 /,如 proxy_pass http://backend/;

  • 确认后端能接收未加密流量:如果网关 Nginx 处理了 HTTPS(WSS),那么它转发给下游 Nginx 的可以是 HTTP(WS)。请确保你的下游 Nginx 和后端服务能正确处理这种转发。

  • 启用会话保持 (Sticky Sessions):对于有状态的应用,应在目标组(Target Group)上启用会话保持,确保来自同一客户端的请求始终到达同一后端

  • 检查安全组:确保 LB 的安全组允许来自客户端和去往后端的目标端口(如 80/443)的流量

三、验证步骤

1. 检查 Gateway 和 Nginx 路由是否生效

curl -v -H "Host: test.com.cn" \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Key: $(openssl rand -base64 16)" \
  -H "Sec-WebSocket-Version: 13" \
  https://网关IP:网关端口/ws/channel/checkHost?id=xxx

预期返回 101 Switching Protocols

使用 websocat 工具测试:brew install websocat(mac安装)

  • 使用 websocat ws://test.com.cn/ws/ 测试 WS。

  • 使用 websocat -k wss://test.com.cn/ws/ 测试 WSS(自签名证书需加 -k 忽略验证)。

  • 在线验证:http://tool0.com/websocket/

测试普通 HTTP 请求

curl -v https://test.com.cn/ws/channel/checkHost?id=xxx

应正常返回业务数据。

2. 查看 Gateway 和 Nginx 日志

application.yml 中为 org.springframework.cloud.gateway 开启 DEBUG 级别日志,观察请求被匹配到了哪条路由。

logging:
  level:
    org.springframework.cloud.gateway: DEBUG    
    org.springframework.web: DEBUG

观察请求被哪个路由匹配。

查看 Nginx 错误日志

  • tail -f /var/log/nginx/error.log,可定位连接后端失败或 SSL 错误。

  • tail -f /var/log/nginx/access.log,可观察请求被哪个路由匹配

3. 分阶段验证

先验证后端服务是否正常,然后排查 Nginx 配置,再访问 Gateway 服务(绕过 Nginx),确认 Gateway 配置

  • 测试验证后端服务 ws 连接是否正常

  • 再通过 Nginx 访问:https://test.com.cn/ws/...

  • 访问 Gateway(绕过 Nginx):https://网关IP:端口/ws/...

四、常见错误及处理

在配置 WebSocket 代理或客户端时,最常见的错误往往源于反向代理(如 Spring Cloud GatewayNginx)的配置缺失网络环境干扰SSL/TLS 证书问题。下表汇总了典型错误现象、可能原因及对应解决方案,快速定位问题。


参考: