Nginx代理FastAPI WebSocket连接成功但客户端收不到服务端消息求助
排查解决步骤
1. 修复Nginx配置核心错误
你当前配置的WebSocket头写法错误,是该问题的核心诱因:你把Upgrade头写死为固定字符串websocket,Connection头也没有适配动态升级逻辑,直接导致Nginx代理时WebSocket握手状态异常,服务端实际未完成完整连接建立,但客户端误以为连接成功。
将你的Nginx location块替换为如下配置:
location /ws { proxy_pass http://ta-solution:8001; proxy_http_version 1.1; # 替换写死的Upgrade头为动态读取请求头的值 proxy_set_header Upgrade $http_upgrade; proxy_set_header 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; # 关闭缓存、缓冲,避免消息滞留 proxy_buffering off; proxy_cache off; proxy_connect_timeout 1d; proxy_send_timeout 1d; proxy_read_timeout 1d; }
2. 校验路径转发规则
你的客户端请求路径是/ws/index,当前proxy_pass末尾没有斜杠,Nginx会把完整的/ws/index路径转发到后端服务。请确认你的FastAPI路由是否匹配该路径:
- 如果后端WebSocket路由是
@app.websocket("/ws/index"),无需调整 - 如果后端WebSocket路由是
@app.websocket("/index"),需要将proxy_pass改为http://ta-solution:8001/(末尾加斜杠),Nginx会自动剔除/ws前缀,转发/index到后端
3. 修复服务端异常处理逻辑
你当前服务端代码的异常捕获块中,未判断连接状态就直接调用close(),才会触发第二个RuntimeError: Cannot call "send" once a close message has been sent.报错,可优化异常处理逻辑:
from starlette.websockets import WebSocketState # 你的websocket接口异常处理部分 try: data = await websocket.receive_text() # 原有业务逻辑 except AssertionError: # 先判断连接状态再执行关闭 if websocket.application_state == WebSocketState.CONNECTED: await websocket.close()
4. 生效验证
修改完成后执行nginx -s reload重载Nginx配置,重启FastAPI服务后重新测试即可。
内容的提问来源于stack exchange,提问作者jong
相关产品推荐
相关产品推荐

