Skip to content

WebSocket 服务高并发部署与运维指南

在生产环境中部署高并发(10 万+ 连接)的 WebSocket 服务时,必须针对操作系统内核、反向代理服务器以及进程管理实施深度调优,以保证长连接的低延迟与稳定性。


1. 进程管理 (Supervisor)

我们使用 Supervisor 来守护后台 WebSocket 服务进程。在负载较大的环境下,为了充分利用 CPU 多核性能,建议在不同的内部端口上拉起多个实例,并由 Nginx 进行负载均衡。

创建配置文件 /etc/supervisor/conf.d/websocket-reverb.conf:

ini
[program:websocket-reverb]
process_name=%(program_name)s_%(process_num)02d
# 启动 4 个实例分摊高并发 CPU 消耗
command=php artisan reverb:start --host=127.0.0.1 --port=%(expr:8080+process_num)s
numprocs=4
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/supervisor/websocket.log
# 提高当前守护进程的最大打开文件句柄数
minfds=100000

2. Nginx 反向代理与 WSS 调优

为了支持安全套接字连接(wss://)并隐藏内部端口,Nginx 必须作为反向代理,同时承担 SSL 卸载的职责。

nginx
# 1. 定义上游负载均衡服务器集群
upstream websocket_servers {
    ip_hash; # 必须使用 ip_hash 算法保持长连接粘性
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8083 max_fails=3 fail_timeout=30s;
    keepalive 128; # 保持上游连接池活跃数
}

server {
    listen 443 ssl http2;
    server_name ws.example.com;

    # SSL 证书配置
    ssl_certificate /etc/letsencrypt/live/ws.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ws.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://websocket_servers;
        
        # 必须:开启 HTTP/1.1 并转发 WebSocket 特有的协议升级头部
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header 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 https;
        
        # 核心:将超时时间从默认的 60 秒延长至 1 小时,防止 Nginx 在客户端没有心跳时异常挂断
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        
        # 开启缓冲禁用,实现真正的零延迟数据流推送
        proxy_buffering off;
    }
}

3. 操作系统内核级优化 (Linux Kernel)

默认的 Linux 系统参数限制了单台机器能支持的最大长连接并发数(通常文件描述符限制为 1024)。在生产环境下,必须按以下步骤调优。

3.1 增加打开文件句柄上限

编辑 /etc/security/limits.conf,增加 www-data 用户(或运行该服务的用户)的系统资源限额:

text
www-data  soft  nofile  100000
www-data  hard  nofile  100000

3.2 优化 TCP 协议栈参数

编辑系统配置文件 /etc/sysctl.conf,添加以下内核调优指令:

ini
# 提高系统全局最大打开文件数限制
fs.file-max = 2097152

# 扩大可分配的临时端口范围,防止并发端口耗尽
net.ipv4.ip_local_port_range = 1024 65535

# 启用 TCP 连接快速回收与重用 (防止积累过多的 TIME_WAIT 状态连接)
net.ipv4.tcp_tw_reuse = 1

# 调大系统积压(Backlog)队列深度,防止高频握手时产生连接溢出
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 16384

# 优化内存缓存区,以支持大量低吞吐长连接占用的内存
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

执行以下指令以立即应用内核更改:

bash
sudo sysctl -p

4. Redis 集群与横向扩展机制

当单台 WebSocket 服务器在硬件上遭遇瓶颈时,我们需要在多台服务器上横向部署。

为了使运行在不同服务器(例如 Server A 和 Server B)上的客户端能够实现消息互通,需要在后台将它们绑定到统一个 Redis 集群中:

  1. 发布端 (Publish): 当 Laravel 业务后台有数据要推送给用户,将报文发布到公用的 Redis 服务上。
  2. 订阅端 (Subscribe): 所有运行在多台服务器上的独立 WebSocket 实例均长连接订阅该 Redis 频道。收到事件后,本地实例会寻找当前连在本机上的用户并精准投递。