需将 Nginx error_log 调至 debug 级别并配置自定义 access_log,重点检查 Upgrade/Connection 头透传、HTTP/1.1 版本设置及上游响应状态,才能精准定位 WebSocket 握手失败原因。

要精准定位 WebSocket 握手失败原因,单靠前端报错或后端日志远远不够。Nginx 作为代理入口,其错误日志(error_log)在默认级别下通常不记录协议升级细节,必须主动调高日志粒度并配合关键配置,才能捕获握手阶段的真实问题根源。
开启 debug 级别错误日志
Nginx 的 error_log 默认为 error 或 warn 级别,对握手失败仅输出笼统的“upstream refused”或“connection refused”,无法反映 Upgrade 头是否丢失、HTTP 版本是否降级等关键信息。
需在全局或对应 server 块中启用:
error_log /var/log/nginx/websocket_error.log debug;- 确保编译时已启用
--with-debug(多数官方包默认包含) - 重启 Nginx 后,日志将详细打印每个请求的头字段传递过程,例如:
"http proxy header: "Upgrade: websocket"" 表示头已捕获;
"http proxy header: "Connection: upgrade"" 表示 Connection 头被正确设置;
若缺失这两行,则直接确认是头透传配置未生效。
结合 access_log 记录原始请求头
debug 日志虽细,但不易快速筛选。建议同时增强 access_log,显式记录客户端发起的 Upgrade 和 Connection 头:
- 定义自定义日志格式:
log_format ws_debug '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_upgrade" "$http_connection" "$upstream_http_upgrade" "$upstream_http_connection";' - 在 location 块中启用:
access_log /var/log/nginx/ws_handshake.log ws_debug; - 成功握手时,日志中
$http_upgrade应为websocket,$upstream_http_upgrade也应一致;若前者有值而后者为空,说明proxy_set_header Upgrade $http_upgrade未生效或变量未被识别。
重点观察 debug 日志中的三类关键线索
启用 debug 后,重点关注以下三类日志片段:
-
HTTP 协议版本降级提示:如出现 "using HTTP/1.0 to backend",说明
proxy_http_version 1.1未生效,必然导致握手失败 -
头字段丢弃警告:如 "discarding header 'Upgrade'" 或 "header 'Connection' not passed",直指
proxy_set_header配置缺失或拼写错误 - 上游响应状态异常:如 "upstream sent no valid HTTP/1.0 header" 或 "upstream rejected request with error 400",结合前两点可判断是后端拒绝(因头缺失)还是网络中断











