跨GCP项目GCE LB访问Cloud Run上Streamlit应用的WebSocket错误排查
问题
我的应用基础设施架构如下:
GCE Global LB(中央GCP项目)=> Internet NEG => Cloud Run应用(独立项目中的Streamlit应用)
已知很多用户在Cloud Run上部署Streamlit应用时会碰到WebSocket相关问题,但直接访问应用时一切正常。以下两种场景下应用运行无异常:
- 直接通过Cloud Run URL访问,例如
https://myapp-abc123-uc.a.run.app - 在同一项目内创建GCE LB,通过无服务器后端连接到Cloud Run应用
现在我的GCE LB位于中央项目,需要将流量路由到其他项目的Cloud Run应用,采用指向Cloud Run应用URL的Internet NEG(并配置请求头)的方式。目前流量路由功能正常,但通过负载均衡器访问时,Streamlit应用抛出错误:
WebSocket connection to 'wss://my.domain.com/my_app/_stcore/stream' failed:
当前LB路由规则为:URL映射中的路径/my_app => 设置请求头host: myapp-abc123-uc.a.run.app的后端 => FQDN为run.app的Internet NEG
怀疑是当前URL路由方式破坏了WebSocket连接,请问该如何修复这个错误?是否需要修改代码、显式传递请求头?
修复方案
1. 修正WebSocket请求的路径与Host映射
Streamlit的WebSocket请求会基于当前访问的域名(my.domain.com)和路径前缀(/my_app)生成连接地址,但Cloud Run后端期望的Host是自身的myapp-abc123-uc.a.run.app,且需要将带前缀的WebSocket路径转发为后端原生路径。
需在LB的URL映射中添加特殊路由规则:
- 匹配路径
/my_app/_stcore/stream - 转发时移除路径前缀,将路径改写为
/_stcore/stream - 保留原有的
host: myapp-abc123-uc.a.run.app请求头配置
2. 确保WebSocket必要请求头被传递
GCE LB原生支持WebSocket,但需保证以下协议相关头信息完整传递到Cloud Run后端:
Upgrade: websocketConnection: UpgradeSec-WebSocket-Key、Sec-WebSocket-Version
检查LB的后端服务配置,若有请求头修改规则,需确保上述头信息未被移除或篡改。
3. 配置Streamlit适配路径前缀(可选)
如果路由调整仍有问题,可在Streamlit启动时指定根路径,让应用适配LB的前缀:
启动命令添加参数:
streamlit run your_app.py --server.baseUrlPath /my_app
这样Streamlit生成的WebSocket连接会自动包含/my_app前缀,无需LB做路径改写,配合Host头配置即可让后端正确识别请求。
验证方法
修改配置后,通过浏览器开发者工具「网络」面板检查:
- 确认WebSocket请求URL为
wss://my.domain.com/my_app/_stcore/stream - 查看请求头的
Host是否为myapp-abc123-uc.a.run.app - 检查响应状态是否为
101 Switching Protocols
内容的提问来源于stack exchange,提问作者red888

