可以!Envoy需显式配置upgrade_configs并设upgrade_type为websocket,Go服务须监听0.0.0.0,且必须透传Connection和Upgrade头,否则握手失败导致前端卡在CONNECTING状态。
Envoy对WebSocket的支持不是默认开启的
envoy默认把所有http请求当普通短连接处理,websocket 协议需要显式声明升级逻辑,否则握手阶段就失败——浏览器发 upgrade: websocket,envoy直接返回 400 或 426。关键不是“能不能代理”,而是“有没有告诉envoy这是websocket”。
必须在 route 配置里加 upgrade_configs,且 upgrade_type 必须设为 websocket:
route: upgrade_configs: - upgrade_type: websocket
漏掉这一项,哪怕后端Go服务完全正确,前端也卡在 CONNECTING 状态。
Go服务监听地址不能写127.0.0.1或localhost
在Kubernetes或Sidecar模式下,Envoy和Go进程同属一个Pod,但网络命名空间隔离。如果Go服务绑定 127.0.0.1:8080,Envoy从 localhost:8080 访问会失败(它看到的是自己的回环,不是Go的)。
必须让Go服务监听 0.0.0.0:8080,确保Envoy能通过Pod IP或ClusterIP访问到它:
-
http.ListenAndServe("0.0.0.0:8080", handler)—— 正确 -
http.ListenAndServe("127.0.0.1:8080", handler)—— 在Sidecar场景下必挂 - 若用
gorilla/websocket,Upgrader.CheckOrigin也要允许实际来源(比如"*"仅限调试,生产应校验Origin头)
Envoy配置里必须透传Connection和Upgrade头
WebSocket握手依赖两个关键HTTP头:Connection: upgrade 和 Upgrade: websocket。Envoy默认可能过滤或重写它们,尤其在启用了某些HTTP/2优化或安全策略时。
需在 route 或 virtual_host 层级显式放行:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
headers_to_add:
- header:
key: "Connection"
value: "upgrade"
- header:
key: "Upgrade"
value: "websocket"更稳妥的做法是禁用自动头清理,在 route 中加:
clear_route_cache: false suppress_envoy_headers: false
否则你看到的错误可能是:Firefox/Safari能连上,Chrome报 1006 —— 这往往就是 Connection 头被悄悄干掉了。
健康检查路径别和WebSocket路径冲突
Envoy常配 liveness_probe 或主动健康检查(如 GET /healthz),但如果路由规则把 /ws 和 /healthz 都匹配到同一 route,而该 route 又启用了 upgrade_configs,健康检查就会被当成WebSocket升级请求,返回 400 或超时。
解决方式只有两个:
- 为健康检查单独配一条精确匹配的
route,放在WebSocket路由之前,且不带upgrade_configs - 改用非HTTP的健康检查机制(如TCP探针),绕过HTTP层解析
这个坑特别隐蔽:服务看起来“能连”,但滚动更新时频繁被驱逐——因为健康检查一直失败。

















