Nginx 报错 unknown connection_upgrade variable 完整解决方案

问题描述

在使用 Nginx 配置 WebSocket 或反向代理时,可能会遇到以下错误:

nginx: [emerg] unknown "connection_upgrade" variable
nginx: configuration file /etc/nginx/nginx.conf test failed

这个错误表明 Nginx 配置文件中使用了 $connection_upgrade 变量,但该变量未定义。

错误原因

$connection_upgrade 变量通常用于 WebSocket 配置,支持 Upgrade 头部的处理。但 Nginx 默认不识别这个变量,需要通过 map 指令手动定义。

常见触发场景

场景是否需要 WebSocket常见配置
普通 Web 应用❌ 不需要HTTP/HTTPS
实时聊天应用✅ 需要WebSocket
API 网关❌ 不需要REST API
在线协作工具✅ 需要WebSocket
直播/流媒体✅ 需要WebSocket/RTMP

解决方案

方案一:添加 map 配置(推荐 - 需要 WebSocket)

如果你需要 WebSocket 支持,在 /etc/nginx/nginx.conf 的 http 块中添加以下配置:

http {
    # ... 其他配置 ...
    
    # 添加 WebSocket 支持的 map 配置
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    # ... 其他配置 ...
}

配置说明

  • map 指令:根据 $http_upgrade 的值设置 $connection_upgrade
  • default upgrade:默认情况下允许 Upgrade
  • '' close:如果 Upgrade 头为空,则关闭连接

完整配置示例

http { include /etc/nginx/mime.types; default_type application/octet-stream; # WebSocket 支持配置 map $http_upgrade $connection_upgrade { default upgrade; '' close; } # 基础配置 sendfile on; keepalive_timeout 65; # 上游服务器 upstream backend { server 127.0.0.1:8080; } # 服务器配置 server { listen 80; server_name example.com; location / { proxy_pass http://backend; proxy_http_version 1.1; # WebSocket 支持 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $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; } } }

方案二:移除 WebSocket 配置(不需要 WebSocket)

如果你不需要 WebSocket 支持,可以直接移除相关配置:

location / { proxy_pass http://backend; # 保留基础代理头 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_set_header Upgrade $http_upgrade; # proxy_set_header Connection $connection_upgrade; }

方案三:使用独立的 WebSocket 配置文件

将 WebSocket 配置提取到独立文件,便于管理:

# 创建 WebSocket 配置文件
sudo tee /etc/nginx/conf.d/websocket.conf << 'EOF'
# WebSocket 支持配置
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
EOF

# 在 nginx.conf 中引用
# http 块中添加:
include /etc/nginx/conf.d/*.conf;

验证和测试

1. 测试配置文件

# 测试 Nginx 配置
sudo nginx -t

# 成功输出示例:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

2. 重载 Nginx

# 重载配置(推荐)
sudo nginx -s reload

# 或者重启服务
sudo systemctl restart nginx

# 检查状态
sudo systemctl status nginx

3. 验证 WebSocket 连接

# 使用 curl 测试 Upgrade 头
curl -i -H "Upgrade: websocket" -H "Connection: Upgrade" http://example.com

# 使用 wscat 测试 WebSocket(需要安装)
npm install -g wscat
wscat -c ws://example.com/websocket

4. 查看 Nginx 日志

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

# 查看访问日志
sudo tail -f /var/log/nginx/access.log

# 实时查看连接状态
sudo nginx -T | grep -A 10 "location"

常见问题排查

问题 1:配置后仍然报错

# 检查 map 配置位置(必须在 http 块内)
sudo nginx -T | grep -A 5 "map"

# 检查配置文件语法
sudo nginx -t

# 检查文件权限
ls -la /etc/nginx/nginx.conf

问题 2:WebSocket 连接失败

# 检查后端服务是否运行
netstat -tlnp | grep 8080

# 检查防火墙规则
sudo ufw status
sudo firewall-cmd --list-ports

# 测试后端直连
curl http://127.0.0.1:8080

问题 3:配置不生效

# 强制重载 Nginx
sudo systemctl stop nginx
sudo systemctl start nginx

# 检查是否有多个 nginx.conf
find /etc -name "nginx.conf"

# 查看实际加载的配置
sudo nginx -T

性能优化建议

WebSocket 连接优化

http { # ... 其他配置 ... map $http_upgrade $connection_upgrade { default upgrade; '' close; } # WebSocket 超时配置 map $http_upgrade $timeout_upgrade { default 3600s; '' 75s; } server { location /websocket { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # 优化配置 proxy_buffering off; proxy_cache off; proxy_read_timeout $timeout_upgrade; proxy_send_timeout $timeout_upgrade; } } }

连接池配置

upstream backend { server 127.0.0.1:8080; # 连接池配置 keepalive 32; keepalive_requests 100; keepalive_timeout 60s; }

安全加固建议

1. 限制 WebSocket 路径

# 只允许特定路径使用 WebSocket location /api/ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } # 其他路径禁止 WebSocket location / { proxy_pass http://backend; # 检查是否尝试 Upgrade if ($http_upgrade) { return 400; } }

2. 添加认证

location /websocket { # JWT 认证 auth_request /auth; proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } location = /auth { internal; proxy_pass http://auth-service/validate; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; }

3. 限流配置

http { # 限制连接速率 limit_conn_zone $binary_remote_addr zone=websocket_limit:10m; server { location /websocket { limit_conn websocket_limit 10; # 每个 IP 最多 10 个连接 proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } } }

总结

Nginx 报错 unknown "connection_upgrade" variable 的解决方案:

  1. 需要 WebSocket:在 http 块中添加 map 配置定义变量
  2. 不需要 WebSocket:移除 Upgrade 相关配置
  3. 验证配置:使用 nginx -t 测试,nginx -s reload 重载
  4. 性能优化:配置超时、连接池、缓冲
  5. 安全加固:路径限制、认证、限流

根据你的实际需求选择合适的方案,确保 Nginx 配置正确运行!🚀


相关文章:

发表回复

后才能评论