You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker环境下Nginx代理WebSocket遇客户端连接关闭错误求助

解决Nginx作为WebSocket代理时出现"client closed connection while waiting for request"的问题

从你的描述来看,WebSocket能成功建立连接但随后出现这个Nginx日志,核心原因是你的Nginx代理缺少WebSocket长连接所需的关键配置——虽然握手成功了,但后续Nginx没有正确维持连接,导致客户端主动断开。下面是具体的修复方案:

一、修正Nginx配置(核心步骤)

你的nginx.conf需要添加WebSocket代理必需的HTTP头和超时设置,以下是最简可用的配置示例:

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 8888;
        server_name localhost;

        location /ws {
            # 关键配置:支持WebSocket协议升级
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            
            # 调长超时时间,避免长连接被提前断开
            proxy_connect_timeout 7d;
            proxy_send_timeout 7d;
            proxy_read_timeout 7d;
            
            # 替换为你的WebSocket服务的容器名称和端口(比如docker-compose里的服务名是ws,端口5000)
            proxy_pass http://ws:5000;
        }
    }
}

关键配置解释:

  • proxy_http_version 1.1;:WebSocket握手依赖HTTP/1.1协议,必须强制Nginx使用这个版本转发请求,否则无法完成后续的长连接交互。
  • proxy_set_header Upgrade $http_upgrade; 和 proxy_set_header Connection "upgrade";:这两个头是让Nginx识别客户端的WebSocket升级请求,并把这个指令完整转发到后端服务,确保连接能维持长连接状态。
  • 超时设置:默认的Nginx代理超时(比如proxy_read_timeout默认60秒)太短,WebSocket是长连接场景,可能长时间没有数据传输,调长超时可以避免Nginx或客户端因为超时主动断开连接。

二、验证其他配置文件的正确性

  1. docker-compose.yml:确保Nginx和WebSocket服务在同一个Docker网络,并且Nginx的proxy_pass指向正确的服务名和端口。示例:
    version: '3'
    services:
      nginx:
        build: ./nginx
        ports:
          - "8888:8888"
        networks:
          - ws-network
      ws:
        build: ./ws
        networks:
          - ws-network
    networks:
      ws-network:
        driver: bridge
    
  2. server.py:确保WebSocket服务正常监听端口,比如用aiohttp的最简示例:
    from aiohttp import web
    
    async def websocket_handler(request):
        ws = web.WebSocketResponse()
        await ws.prepare(request)
        print("WebSocket connection established")
        async for msg in ws:
            if msg.type == web.WSMsgType.TEXT:
                await ws.send_str(f"Received: {msg.data}")
            elif msg.type == web.WSMsgType.ERROR:
                print(f"WebSocket error: {ws.exception()}")
        print("WebSocket connection closed")
        return ws
    
    app = web.Application()
    app.add_routes([web.get('/ws', websocket_handler)])
    
    if __name__ == '__main__':
        web.run_app(app, host='0.0.0.0', port=5000)
    
  3. Dockerfile(nginx):确保正确复制配置文件到容器内的Nginx配置目录,比如:
    FROM nginx:alpine
    COPY nginx.conf /etc/nginx/nginx.conf
    
  4. Dockerfile(ws):确保安装依赖并启动服务,比如:
    FROM python:3.9-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    COPY server.py .
    CMD ["python", "server.py"]
    
    (requirements.txt里需要添加aiohttp)

三、测试验证

  1. 重新构建并启动容器:docker-compose up --build
  2. 在浏览器控制台执行以下代码连接WebSocket:
    const ws = new WebSocket('ws://localhost:8888/ws');
    ws.onopen = () => {
        console.log('WebSocket连接成功!');
        ws.send('Hello from browser');
    };
    ws.onmessage = (e) => console.log('收到后端消息:', e.data);
    ws.onerror = (e) => console.error('连接错误:', e);
    ws.onclose = (e) => console.log('连接关闭:', e);
    
  3. 查看Nginx日志,确认不再出现client closed connection while waiting for request的错误,同时后端服务会打印连接建立的日志。

这样应该就能解决你的问题了,本质上就是Nginx默认配置不支持WebSocket的长连接维持,补上关键配置即可。

内容的提问来源于stack exchange,提问作者deathangel908

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:27:13