Spring Cloud Gateway 的 WebSocket 路由必须使用 ws:// 或 lb:ws:// 协议前缀,跨域需配置 allowedOriginPatterns 并启用 add-to-simple-url-handler-mapping,Socket.IO 需覆盖 /socket.io 及其轮询路径,且过滤器仅作用于握手阶段。

Spring Cloud Gateway 默认支持 WebSocket,但直接照搬 HTTP 路由配置会失败——连接建立后秒断、跨域报错、负载均衡不生效,根本原因是 WebSocket 升级流程与响应式模型的冲突没被处理。
WebSocket 路由必须用 ws:// 或 wss:// 协议前缀
Gateway 的 WebsocketRoutingFilter 只识别以 ws:// 或 wss:// 开头的 uri。如果写成 http:// 或省略协议,请求会被当成普通 HTTP 处理,握手失败。
-
uri: ws://192.168.1.100:8081✅ 正确,触发 WebSocket 代理逻辑 -
uri: http://192.168.1.100:8081❌ 转发为 HTTP,后端收不到 Upgrade 请求 -
uri: lb://socketio-service❌ 缺少协议,网关无法识别为 WebSocket 流量 - 正确写法应为
uri: lb:ws://socketio-service,其中lb:ws://是 Gateway 特有语法,表示“走负载均衡的 WebSocket”
CorsWebFilter 在 WebSocket 握手阶段会抛 UnsupportedOperationException
错误日志里出现 ReadOnlyHttpHeaders.put 报空指针或不支持操作,基本就是这个原因:Netty 在完成 WebSocket 升级响应时已提交 headers,而全局 CORS 过滤器仍试图修改它。
- 不要用传统的
allowedOrigins(已过时),改用allowedOriginPatterns - 必须开启
add-to-simple-url-handler-mapping: true,否则跨域配置对 WebSocket 不生效 - 配置需放在
globalcors下,且路径匹配要覆盖 WebSocket 握手路径(如/socket.io/**) - 示例关键项:
spring: cloud: gateway: globalcors: add-to-simple-url-handler-mapping: true cors-configurations: '[/socket.io/**]': allowedOriginPatterns: "*" allowedMethods: ["GET", "OPTIONS"] allowCredentials: true
Socket.IO 等封装库需要绕过默认心跳和路径重写
Socket.IO 客户端默认带查询参数(?EIO=4&transport=polling)并频繁发起 HTTP 轮询升级,Gateway 的 Path 断言若只配 /socket.io/**,会漏掉初始 polling 请求;同时其心跳包可能被某些过滤器(如超时设置)中断。
- 务必把断言扩展到根路径:
- Path=/socket.io/**, /socket.io(注意末尾无斜杠的原始路径) - 禁用可能干扰长连接的过滤器:比如
RetryGatewayFilterFactory、自定义超时WriteResponseFilter等 - 避免使用
RewritePath过滤器重写 WebSocket 路径——重写后 Sec-WebSocket-Key 等头可能失效 - 若后端是 Socket.IO Server,建议在网关层关闭自动压缩:
spring: cloud: gateway: httpclient: compress: false
最易被忽略的是:WebSocket 连接建立后,所有数据帧都绕过 Gateway 的大部分过滤器链,只走 WebsocketRoutingFilter。这意味着你在路由里加的鉴权、日志、Header 修改等局部过滤器,对实际消息传输完全无效——它们只作用于握手阶段那一个 HTTP 请求。


















