SignalR JavaScript客户端连接30秒后断开,如何解决?
解决Playfab托管SignalR连接30秒自动断开问题
针对你遇到的连接在Ping后被服务器主动关闭的问题,可从以下几个方向排查修复:
1. 配置正确的心跳与重连策略
SignalR依赖Ping/Pong机制维持连接,若客户端心跳间隔或服务器超时设置不合理,会触发服务器主动断开。手动调整参数并开启自动重连:
connection = new signalR.HubConnectionBuilder() .withUrl(`url`, { withCredentials: false, httpClient: new SignalRClient(), headers: { 'X-EntityToken': entity.EntityToken, }, }) .withAutomaticReconnect([0, 2000, 10000, 30000]) // 阶梯式自动重连 .configureLogging(signalR.LogLevel.Information) // 开启日志便于排查 .build(); // 延长服务器超时与心跳间隔 connection.serverTimeoutInMilliseconds = 60000; // 服务器无响应60秒后判定断开 connection.keepAliveIntervalInMilliseconds = 15000; // 每15秒发送一次心跳Ping await connection.start();
2. 确保EntityToken持续有效
Playfab的EntityToken存在有效期,若连接建立后token过期,服务器会主动断开连接。需定期检查并刷新token:
// 假设你有获取新EntityToken的方法getNewEntityToken() async function refreshTokenAndReconnect() { const newEntity = await getNewEntityToken(); await connection.stop(); // 用新token重建连接 connection = new signalR.HubConnectionBuilder() .withUrl(`url`, { withCredentials: false, httpClient: new SignalRClient(), headers: { 'X-EntityToken': newEntity.EntityToken, }, }) .withAutomaticReconnect() .build(); await connection.start(); // 重新订阅所有事件 subscribeToYourEvents(connection); } // 每分钟检查一次token有效期,提前5分钟刷新 setInterval(async () => { const expiryDate = new Date(entity.EntityToken.Expiration); const timeUntilExpiry = expiryDate.getTime() - Date.now(); if (timeUntilExpiry < 300000) { // 剩余时间小于5分钟时刷新 await refreshTokenAndReconnect(); } }, 60000);
3. 排查自定义HttpClient的问题
你使用了自定义的SignalRClient作为httpClient,若该客户端未正确处理SignalR的Ping帧响应,会导致服务器判定客户端离线。可先移除自定义客户端测试:
connection = new signalR.HubConnectionBuilder() .withUrl(`url`, { withCredentials: false, // 暂时注释掉自定义httpClient,使用默认实现 // httpClient: new SignalRClient(), headers: { 'X-EntityToken': entity.EntityToken, }, }) .withAutomaticReconnect() .build(); await connection.start();
若连接恢复正常,则需检查自定义HttpClient的实现,确保它能正确处理SignalR的WebSocket或长轮询请求,尤其是Ping/Pong帧的响应逻辑。
4. 给事件订阅添加错误捕获
若事件处理回调中存在未捕获的异常,可能间接导致连接断开。给所有事件订阅添加错误处理:
connection.on("TargetEventName", (data) => { try { // 你的事件处理逻辑 console.log("Received event data:", data); } catch (err) { console.error("Event handler error:", err); } }); // 监听连接关闭事件,记录错误详情 connection.onclose((error) => { console.error("Connection closed reason:", error?.message || "Unknown error"); });
内容的提问来源于stack exchange,提问作者Gloria STANCIU
相关产品推荐
相关产品推荐

