PubNub长时间无活动后新旧客户端消息交互异常排查与解决
问题描述
两个客户端订阅同一频道时初始通信正常,但1小时无活动后,原有客户端互发消息仍正常;但重新连接旧客户端或新增新客户端到同一频道时,最初的旧客户端无法接收新客户端发送的消息,新客户端却能接收旧客户端的所有消息。
客户端配置代码:
let config = { publishKey: pubKey, subscribeKey: subKey, userId: userId, ssl: true, presenceTimeout: 300, heartbeatInterval: 60, heartbeatTimeout: 120, keepAlive: true, restore: true, autoNetworkDetection: true, wildcardSubscribe: true, leaveOnUnsubscribe: true }; let client = new PubNub(config);
订阅代码:
client.subscribe({ channels: ["myChannelName"], timeout: 1200 });
解决方案
1. 修正订阅超时与心跳配置
当前订阅的timeout: 1200(20分钟)可能导致长时间无活动后,旧客户端的订阅会话实际已失效但本地未感知。同时心跳相关配置存在冲突,服务端与客户端的在线状态不同步:
- 修改配置参数,让心跳与状态超时逻辑匹配:
let config = { // 保留原有其他配置 heartbeatInterval: 30, // 缩短心跳间隔,确保服务端持续感知客户端在线 heartbeatTimeout: 90, // 超时时间设为间隔的3倍,避免误判离线 presenceTimeout: 180, // 与心跳超时匹配,加快离线状态同步 }; - 移除订阅的
timeout参数,保持长期订阅:client.subscribe({ channels: ["myChannelName"] });
2. 添加订阅状态监听与主动重连处理
通过监听状态事件,在连接、重连或断开时主动确认订阅,确保会话与服务端同步:
client.addListener({ status: function(statusEvent) { if (statusEvent.category === "PNConnectedCategory" || statusEvent.category === "PNReconnectedCategory") { // 连接/重连后重新确认订阅 client.subscribe({ channels: ["myChannelName"], withPresence: true }); } else if (statusEvent.category === "PNDisconnectedCategory") { // 断开后延迟5秒重新订阅 setTimeout(() => { client.subscribe({ channels: ["myChannelName"] }); }, 5000); } } });
3. 调整restore配置逻辑
restore: true会尝试恢复旧会话,但长时间无活动后服务端会话可能已被清理,导致新旧客户端会话不同步:
- 可先尝试关闭
restore: false,验证问题是否解决; - 若需要保留恢复功能,在重连后强制触发订阅刷新,确保会话与服务端一致。
4. 确保userId全局唯一
每个客户端的userId必须是唯一值,避免不同客户端复用ID导致服务端混淆会话状态,引发消息路由错误。
5. 验证Presence状态同步
监听Presence事件,确认新客户端加入时旧客户端能收到join事件,验证状态感知是否正常:
client.addListener({ presence: function(presenceEvent) { console.log(`客户端 ${presenceEvent.uuid} 状态变更: ${presenceEvent.action}`); } });
如果旧客户端收不到新客户端的join事件,说明订阅会话存在同步问题,需重新触发订阅。
内容的提问来源于stack exchange,提问作者Mahmudul Hasan Sayan
相关产品推荐
相关产品推荐

