Socket.io服务器重启后重连缓慢:大量连接请求被拒
Socket.io重启后初期连接缓慢问题排查与解决
问题现象
- 重启Nginx代理的Node.js Socket.io进程(v4.7.2)后,初期几分钟内大部分连接请求被拒绝
- 服务器逐个处理连接,玩家重连速度慢且耗时随机,部分客户端需2分钟才能完成Socket连接
- 客户端会立即发起连接请求,排除客户端配置问题
- 服务器5秒内即可就绪,部分玩家能立即重连,排除启动慢问题
- 几分钟后恢复正常,仅重启后出现该问题
- 无I/O阻塞代码,所有Socket事件均采用异步实现
可能的解决方案
1. 调整Nginx连接配置
Nginx重启或后端服务重启后,可能存在连接队列、worker进程初始化延迟,建议调整以下参数:
- 增大
worker_connections,确保能处理足够并发:worker_connections 10240; - 在
listen指令中增加backlog,提升TCP连接队列长度:listen 80 backlog 8192; - 开启
tcp_nopush和tcp_nodelay优化TCP传输效率
示例Nginx配置片段:
http { worker_connections 10240; ... server { listen 80 backlog 8192; tcp_nopush on; tcp_nodelay on; ... location /socket.io/ { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_connect_timeout 10s; proxy_send_timeout 60s; proxy_read_timeout 60s; } } }
2. 优化Socket.io连接参数
- 调整心跳检测参数,避免初期误判连接超时:
const io = require('socket.io')(server, { pingTimeout: 60000, // 延长至60秒 pingInterval: 25000, // 调整为25秒 transports: ['websocket', 'polling'] });
- 启用
allowRequest快速过滤无效请求,减少服务器资源消耗:
const io = require('socket.io')(server, { allowRequest: (req, callback) => { // 替换为实际的请求合法性验证逻辑(如Token、来源检查) const isValid = true; callback(null, isValid); } });
3. 调整系统TCP内核参数
检查是否存在TCP连接队列溢出,调整以下内核参数(需root权限):
- 增大TCP SYN队列:
echo 8192 > /proc/sys/net/ipv4/tcp_max_syn_backlog - 增大监听队列上限:
echo 8192 > /proc/sys/net/core/somaxconn - 启用SYN洪水防护:
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
可将这些配置写入/etc/sysctl.conf实现永久生效:
net.ipv4.tcp_max_syn_backlog = 8192 net.core.somaxconn = 8192 net.ipv4.tcp_syncookies = 1
执行sysctl -p生效。
4. 启用Socket.io集群模式
单进程处理大量连接时,重启后可能存在资源初始化瓶颈,使用集群模式分散压力:
const { createAdapter } = require('@socket.io/cluster-adapter'); const { setupMaster, setupWorker } = require('@socket.io/sticky'); const cluster = require('cluster'); const http = require('http'); if (cluster.isPrimary) { const httpServer = http.createServer(); setupMaster(httpServer, { loadBalancingMethod: "least-connection" // 按最少连接数分配 }); httpServer.listen(3000); // 根据CPU核心数创建worker进程 for (let i = 0; i < require('os').cpus().length; i++) { cluster.fork(); } } else { const httpServer = http.createServer(); const io = require('socket.io')(httpServer); io.adapter(createAdapter()); setupWorker(io); }
内容的提问来源于stack exchange,提问作者Owow
相关产品推荐
相关产品推荐

