Socket.io客户端卡在101状态,持续XHR轮询求助
Socket.io Websocket 协议升级失败问题解决
问题背景
我通过Nginx反向代理搭建了基于Express和Socket.io的SSL服务,目前消息收发看似正常,但仅支持轮询方式;当强制设置transports: ['websocket']时,请求返回101协议切换状态,但实际未完成Websocket协议升级。
服务端代码
const { v4: uuidV4 } = require('uuid') const express = require('express') const app = express() const fs = require('fs') const https = require('https') const options = { key: fs.readFileSync('/etc/ssl/xxx/ssl.key'), cert: fs.readFileSync('/etc/ssl/xxx/ssl.combined'), } const httpsServer = https.createServer(options, app) httpsServer.listen(3000, function () { console.log("Example app listening at %s", httpsServer.address().port); }); const io = require("socket.io")(httpsServer);
Nginx配置
location / { proxy_read_timeout 300s; proxy_connect_timeout 75s; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass https://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } listen 161.97.166.96:443 ssl; ssl_certificate /etc/ssl/xxx/ssl.combined; ssl_certificate_key /etc/ssl/xxx/ssl.key;
解决步骤
修复Nginx Connection头配置
硬编码"upgrade"会导致非Websocket请求出现冲突,替换成动态匹配的配置:- 先在Nginx的
http块中添加映射规则:map $http_upgrade $connection_upgrade { default upgrade; '' close; } - 然后将location块中的
proxy_set_header Connection "upgrade";改为:proxy_set_header Connection $connection_upgrade;
- 先在Nginx的
调整Socket.io服务端配置
由于是反向代理环境,需要让Socket.io信任代理并正确识别客户端请求,修改初始化代码:const io = require("socket.io")(httpsServer, { cors: { origin: "https://你的实际域名", // 替换成你的业务域名 methods: ["GET", "POST"] }, transports: ["websocket", "polling"], // 优先尝试Websocket,失败自动降级轮询 trustProxy: true // 启用反向代理信任 });规范客户端连接配置
不要仅强制['websocket'],保留降级逻辑,确保连接稳定性:const socket = io("https://你的实际域名", { transports: ["websocket", "polling"], reconnection: true });检查SSL证书一致性
确保Nginx和Node.js服务使用完全一致的SSL证书文件,若存在CA根证书,补充到Node.js的https配置中:const options = { key: fs.readFileSync('/etc/ssl/xxx/ssl.key'), cert: fs.readFileSync('/etc/ssl/xxx/ssl.combined'), ca: fs.readFileSync('/etc/ssl/xxx/ssl.ca') // 如有CA证书则添加 }日志排查验证
- 查看Nginx错误日志:
tail -f /var/log/nginx/error.log - 在服务端添加连接日志,确认传输方式:
io.on('connection', (socket) => { console.log('客户端连接成功,传输方式:', socket.conn.transport.name); socket.on('disconnect', () => { console.log('客户端断开连接'); }); });
- 查看Nginx错误日志:
内容的提问来源于stack exchange,提问作者AntonioCorrenti
相关产品推荐
相关产品推荐

