Nginx WebSocket代理 #

一、WebSocket概述 #

1.1 什么是WebSocket #

WebSocket是一种在单个TCP连接上进行全双工通信的协议。与HTTP不同,WebSocket允许服务器主动向客户端推送数据。

1.2 WebSocket特点 #

  • 全双工通信
  • 低延迟
  • 连接保持
  • 二进制数据支持
  • 跨域支持

1.3 WebSocket握手 #

WebSocket连接通过HTTP Upgrade请求建立:

text
GET /ws HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

服务器响应:

text
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

二、基本WebSocket代理 #

2.1 最简配置 #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name ws.example.com;
    
    location /ws {
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

2.2 完整配置 #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name ws.example.com;
    
    location /ws {
        proxy_pass http://backend:8080;
        
        proxy_http_version 1.1;
        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;
        
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        
        proxy_buffering off;
    }
}

三、配置参数详解 #

3.1 Upgrade头处理 #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

这个map指令根据客户端的Upgrade头设置Connection头:

  • 如果有Upgrade头,设置Connection为upgrade
  • 如果没有Upgrade头,设置Connection为close

3.2 超时配置 #

nginx
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
参数 说明 默认值
proxy_read_timeout 读取后端响应超时 60s
proxy_send_timeout 发送请求超时 60s
proxy_connect_timeout 连接后端超时 60s

WebSocket需要长连接,建议设置较长的超时时间。

3.3 缓冲配置 #

nginx
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 8 4k;

WebSocket是实时通信,建议关闭缓冲。

3.4 HTTP版本 #

nginx
proxy_http_version 1.1;

WebSocket需要HTTP/1.1支持。

四、Socket.IO代理 #

4.1 基本配置 #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name socket.example.com;
    
    location /socket.io/ {
        proxy_pass http://backend:3000;
        
        proxy_http_version 1.1;
        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_read_timeout 86400s;
        proxy_buffering off;
    }
}

4.2 多实例配置 #

nginx
upstream socketio_servers {
    ip_hash;
    server backend1:3000;
    server backend2:3000;
    server backend3:3000;
}

server {
    listen 80;
    server_name socket.example.com;
    
    location /socket.io/ {
        proxy_pass http://socketio_servers;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        
        proxy_read_timeout 86400s;
    }
}

4.3 Sticky Sessions #

nginx
upstream socketio_servers {
    ip_hash;
    server backend1:3000;
    server backend2:3000;
}

sticky cookie srv_id expires=1h domain=.example.com path=/;

五、负载均衡 #

5.1 基本负载均衡 #

nginx
upstream ws_backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    location /ws {
        proxy_pass http://ws_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

5.2 会话保持 #

WebSocket需要会话保持,使用ip_hash:

nginx
upstream ws_backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

或使用一致性哈希:

nginx
upstream ws_backend {
    hash $remote_addr consistent;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

5.3 健康检查 #

nginx
upstream ws_backend {
    zone ws_backend 64k;
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}

六、SSL/WSS配置 #

6.1 HTTPS + WSS #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name ws.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ws.example.com;
    
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    
    location /ws {
        proxy_pass http://backend:8080;
        
        proxy_http_version 1.1;
        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;
        
        proxy_read_timeout 86400s;
    }
}

6.2 后端SSL连接 #

nginx
location /ws {
    proxy_pass https://backend:8443;
    
    proxy_ssl_verify off;
    proxy_ssl_server_name on;
    
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

七、不同框架配置 #

7.1 Node.js WebSocket #

nginx
location /ws {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 86400s;
}

7.2 Spring WebSocket #

nginx
location /ws {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Host $host;
    proxy_read_timeout 86400s;
}

7.3 Django Channels #

nginx
location /ws/ {
    proxy_pass http://localhost:8001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Host $host;
    proxy_read_timeout 86400s;
}

7.4 Go WebSocket #

nginx
location /ws {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Host $host;
    proxy_read_timeout 86400s;
}

八、连接限制 #

8.1 连接数限制 #

nginx
limit_conn_zone $binary_remote_addr zone=ws_conn:10m;

server {
    location /ws {
        limit_conn ws_conn 10;
        
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

8.2 请求频率限制 #

nginx
limit_req_zone $binary_remote_addr zone=ws_req:10m rate=10r/s;

server {
    location /ws {
        limit_req zone=ws_req burst=20;
        
        proxy_pass http://backend:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

九、监控与调试 #

9.1 连接状态监控 #

nginx
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

9.2 日志配置 #

nginx
log_format ws '$remote_addr - [$time_local] "$request" '
              '$status $body_bytes_sent '
              'upstream=$upstream_addr '
              'upgrade=$http_upgrade';

location /ws {
    access_log /var/log/nginx/ws.access.log ws;
    
    proxy_pass http://backend:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

9.3 调试技巧 #

nginx
error_log /var/log/nginx/error.log debug;

十、常见问题 #

10.1 连接断开 #

原因: 超时时间过短

解决:

nginx
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

10.2 403 Forbidden #

原因: Upgrade头未正确传递

解决:

nginx
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

10.3 跨域问题 #

解决:

nginx
location /ws {
    proxy_pass http://backend:8080;
    
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization";
    
    if ($request_method = OPTIONS) {
        return 204;
    }
}

10.4 连接数过多 #

解决:

nginx
worker_processes auto;
worker_connections 65535;
worker_rlimit_nofile 65535;

十一、完整配置示例 #

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream ws_backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    keepalive 32;
}

limit_conn_zone $binary_remote_addr zone=ws_conn:10m;

server {
    listen 80;
    server_name ws.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name ws.example.com;
    
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    
    location /ws {
        limit_conn ws_conn 10;
        
        proxy_pass http://ws_backend;
        
        proxy_http_version 1.1;
        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;
        
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
        proxy_connect_timeout 60s;
        
        proxy_buffering off;
    }
    
    location /socket.io/ {
        proxy_pass http://ws_backend;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        
        proxy_read_timeout 86400s;
        proxy_buffering off;
    }
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

十二、总结 #

本章我们学习了:

  1. WebSocket原理:全双工通信和握手过程
  2. 基本配置:Upgrade头处理和超时设置
  3. Socket.IO代理:多实例和会话保持
  4. 负载均衡:ip_hash和一致性哈希
  5. SSL/WSS配置:HTTPS和WSS
  6. 不同框架:Node.js、Spring、Django、Go
  7. 连接限制:连接数和请求频率限制
  8. 监控调试:状态监控和日志配置

掌握WebSocket代理后,让我们进入下一章,学习限流限速!

最后更新:2026-03-27