Nginx 默认仅记录 WebSocket 握手日志,需通过透传 Upgrade/Connection 头、自定义日志格式(含$http_upgrade、$request_time、$sent_http_x_close_reason等变量)及后端配合,才能准确记录连接建立、持续时长与关闭原因。

Nginx 默认的 access_log 对 WebSocket 连接只记录握手阶段(HTTP Upgrade 请求)的日志,后续真正的长连接通信(即 WebSocket 帧数据)不会触发新日志行。要完整记录 WebSocket 长连接生命周期,关键不是“实时记录每一帧”,而是准确记录连接建立、持续时长、关闭原因等关键事件——这需要结合 Nginx 日志变量、状态标记和合理日志格式设计。
启用 Upgrade 和 Connection 头识别
WebSocket 握手依赖 Upgrade: websocket 和 Connection: Upgrade,Nginx 必须在代理配置中显式透传这些头,并允许协议升级:
- 确保
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade";已配置,否则握手失败,根本不会进入长连接阶段 - 若缺少
proxy_http_version 1.1;,Nginx 会降级为 HTTP/1.0,导致 Connection 头被忽略,升级失败
用自定义日志格式捕获连接关键信息
利用 Nginx 内置变量,在 access_log 中记录 WebSocket 握手特征与连接结果:
log_format ws_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upg="$http_upgrade" conn="$http_connection" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time" '
'close="$sent_http_x_close_reason"';-
$http_upgrade和$http_connection可确认是否为 WebSocket 握手请求(值为websocket和Upgrade) -
$request_time记录从接收首字节到发送完响应的总耗时,对握手请求即为建立连接耗时 - 可在后端服务关闭连接时,通过
add_header X-Close-Reason "client_timeout"等方式注入关闭原因,由$sent_http_x_close_reason捕获
区分正常关闭与异常断连
Nginx 本身不感知 WebSocket 数据帧,也无法主动记录连接中断时刻。但可通过以下方式间接推断:
- 客户端主动关闭:后端返回 101 状态码(Switching Protocols)后,若后续收到带
Close帧的响应(如 4xx/5xx 或自定义状态),可由后端在响应头中标识,Nginx 记录该响应 - 超时断连:设置
proxy_read_timeout(默认 60s),超时后 Nginx 主动关闭连接并返回 502/504;此时$status为 502/504,$request_time接近超时值,是重要线索 - 客户端静默掉线:无明确日志,但可通过监控
nginx_stub_status中的 Active connections 变化趋势 + 应用层心跳日志交叉分析
补充方案:结合应用层日志与连接跟踪
仅靠 Nginx 日志无法覆盖整个长连接生命周期。推荐组合使用:
- 后端服务在 WebSocket
onOpen、onClose、onError回调中打点,记录 connection_id、client_ip、user_id、持续时间、关闭码等,时间精度更高 - 开启 Nginx 的
error_log并设为info级别,可捕获连接重置(client closed connection)、上游断连等底层事件 - 用
nginx-module-sts或 OpenResty 的ngx.timer.at实现连接存活探测(进阶),但需谨慎避免性能影响


















