Nginx 代理 WebSocket 时需透传 Upgrade/Connection 头、关闭 proxy_buffering 和 gzip、调大超时至 86400 秒,并禁用压缩与缓冲,才能确保文本和二进制帧无损透传。

Nginx 本身不解析 WebSocket 帧内容,无论是文本帧(opcode = 1)还是二进制帧(opcode = 2),它都作为原始字节流透明转发。真正影响二进制与文本帧传输一致性的,是代理层的缓冲、超时和头透传配置是否到位。
协议升级必须完整,否则帧根本发不出
WebSocket 连接建立前的 HTTP 握手失败,后续所有帧(无论文本或二进制)都无法到达后端: - 必须设置 proxy_http_version 1.1 —— HTTP/1.0 不支持 Upgrade 机制,握手直接 400 - 必须写 proxy_set_header Upgrade $http_upgrade —— 用变量转发,兼容不同客户端(如发 "mqtt" 或自定义协议) - 必须写 proxy_set_header Connection "upgrade" —— 注意是小写 upgrade、英文双引号;若写成 $http_connection,可能带 keep-alive,导致后端收不到升级信号缓冲与压缩必须关闭,否则帧会被破坏
Nginx 若对 WebSocket 流做缓存或重写,会打乱帧边界、合并或截断数据: - proxy_buffering off —— 防止多个 TEXT/BINARY 帧被攒在一起发送,造成粘包或延迟 - gzip off —— WebSocket 帧不可压缩,开启后服务端解码失败,常见于大 ArrayBuffer 传输 - proxy_buffer_size 4k —— 若因某些模块强制要求设 buffer_size,保持最小且不启用多级缓冲 - proxy_set_header X-Accel-Buffering "no" —— 兼容部分 Nginx 版本,强制禁用内部加速缓冲超时必须调大,否则大二进制帧中途断连
默认 60 秒超时对二进制帧(如图片、音频分片、模型权重)极不友好: - proxy_read_timeout 86400 —— 等待上游发送数据的最长时间,覆盖空闲期或分片间隔 - proxy_send_timeout 86400 —— 向上游发送数据的最长时间,避免大帧未发完就被切断 - client_max_body_size 0 —— WebSocket 不走 HTTP body 流程,此项应禁用限制 - tcp_nodelay on —— 关闭 Nagle 算法,小帧(如鼠标坐标、按键)立即送达,不等待凑满包验证帧是否真正透传,不能只看连接成功
连接建立(101 响应)只是起点,需确认帧内容无损: - 前端发送 new Uint8Array([0x01, 0xFF, 0x80]),检查服务端收到的字节是否完全一致 - Wireshark 抓包过滤 websocket,确认 Frame Type 显示 BINARY,Payload Length 与原始匹配 - 若返回 400 或立即断连,优先查 Upgrade/Connection 头是否丢失;若长度错乱或截断,重点查 proxy_buffering 和 gzip 是否残留不复杂但容易忽略


















