使用Solace JS API发送消息时遇WaitingForDNS状态错误
问题描述
调用Solace JavaScript API发送消息到主题队列时,返回错误:
OperationError: Cannot perform operation SEND while in state WaitingForDNS
目标URL可正常ping通且能解析为IP地址,认为该错误提示存在误导性。
代码场景
使用TypeScript编写,核心逻辑为:检查会话是否已创建,未创建则通过Solace工厂创建会话并调用connect(),因未捕获到连接错误便认为会话已连接,但调用send()时仍提示会话处于WaitingForDNS状态。代码片段如下(已移除无关日志):
class TopicPublisher { private getSession() { if (this.session == null) { try { this.log('Creating session for url=' + this.hosturl+' vpn='+this.vpn+' username='+this.username); this.session = this.solace.SolclientFactory.createSession({ // solace.SessionProperties url: this.hosturl, vpnName: this.vpn, userName: this.username, password: this.pass, }); // Set session event handlers try { this.session.connect(); } catch(error : any) { this.log('Could not make connection to existing session. Error: '+error.toString()); this.session = null; } } catch (error: any) { this.log(error.toString()); } } return this.session; } public publish(messageContent: any) { var solaceMessage = this.getSolaceMessage(messageContent); this.log('Publishing message "' + messageContent + '" to topic "' + this.topicName + '"...'); try { // ************************* // This is where SEND fails // ************************* this.getSession().send(solaceMessage); this.log('Message published.'); } catch (error: any) { this.log(error.toString()); } }; }
问题分析与解决方案
核心原因
Solace的connect()方法是异步操作,调用后不会立即完成连接流程,仅触发连接请求。此时会话仍处于WaitingForDNS或其他中间状态,直接调用send()必然失败。代码中仅通过try/catch捕获connect()的同步异常,但异步的连接状态变化不会被该try/catch捕获,导致错误判断连接已成功。
另外,错误提示WaitingForDNS并不一定真的是DNS解析问题,而是会话还未完成初始化流程(包括DNS解析、TCP连接、会话认证等步骤),此时会话状态尚未进入Connected。
解决方案
1. 监听会话状态事件,确保连接完成后再发送消息
必须通过Solace会话的事件监听机制,等待会话进入Connected状态后,再执行消息发送操作。修改代码如下:
class TopicPublisher { private isConnected = false; private connectResolve?: () => void; private connectPromise?: Promise<void>; private getSession(): Promise<solace.Session> { if (this.session && this.isConnected) { return Promise.resolve(this.session); } if (this.connectPromise) { return this.connectPromise.then(() => this.session!); } this.connectPromise = new Promise((resolve, reject) => { this.connectResolve = resolve; try { this.log('Creating session for url=' + this.hosturl+' vpn='+this.vpn+' username='+this.username); this.session = this.solace.SolclientFactory.createSession({ url: this.hosturl, vpnName: this.vpn, userName: this.username, password: this.pass, }); // 设置会话事件处理器 this.session.on(solace.SessionEventCode.UP_NOTICE, () => { this.isConnected = true; this.log('Session connected successfully'); this.connectResolve?.(); }); this.session.on(solace.SessionEventCode.CONNECT_FAILED_ERROR, (error) => { this.log('Connection failed: ' + error.toString()); this.session = null; this.isConnected = false; reject(error); }); // 监听断开事件 this.session.on(solace.SessionEventCode.DISCONNECTED, () => { this.isConnected = false; this.log('Session disconnected'); }); try { this.session.connect(); } catch(error : any) { this.log('Could not initiate connection. Error: '+error.toString()); this.session = null; reject(error); } } catch (error: any) { this.log(error.toString()); reject(error); } }); return this.connectPromise.then(() => this.session!); } public async publish(messageContent: any) { try { const session = await this.getSession(); const solaceMessage = this.getSolaceMessage(messageContent); this.log('Publishing message "' + messageContent + '" to topic "' + this.topicName + '"...'); session.send(solaceMessage); this.log('Message published.'); } catch (error: any) { this.log(error.toString()); } }; }
2. 关键修改点说明
- 将
getSession改为返回Promise,确保只有在连接成功后才返回可用会话 - 添加
isConnected标记跟踪会话连接状态 - 通过
SessionEventCode.UP_NOTICE事件监听连接成功通知,此时才认为会话可用 - 通过
CONNECT_FAILED_ERROR事件捕获异步连接失败的情况,避免错误持有无效会话 publish方法改为异步,等待会话准备完成后再执行发送操作
3. 额外注意事项
- 即使URL能ping通,Solace的连接流程还包含VPN认证、权限校验等步骤,任何一步未完成都会导致会话处于非可用状态
- 建议添加会话断开重连的逻辑,确保在网络波动时能自动恢复连接
- 错误提示
WaitingForDNS是会话状态的真实反映,只是此时的状态不一定由DNS解析失败导致,而是连接流程尚未完成
内容的提问来源于stack exchange,提问作者Woodsman
相关产品推荐
相关产品推荐

