我有一个使用mqtt.js连接到emqx集群的NodeJS应用程序。
MQTT群集包含2个节点,我尝试提供这些节点以使用DNS Round Robin。因此,我有1个A记录(例如mqtt.example.com),它指向2个IP(IP1和IP2)。当两个节点都在线时,我的NodeJS应用程序也可以正常连接并订阅选定的主题。
现在在MQTT节点上,我可以看到应用程序连接到哪个节点。现在,当我停止与应用程序连接的节点时,我希望它(迟早会)故障转移到第二个活动节点。
我还使用了Loraserver(已连接到MQTT的连接器)以及MQTT的Node Red实施进行了测试,并且当我停止它们所连接的节点时,它们都立即连接到了活动节点。
但是我的带有mqtt.js的NodeJS应用程序一直尝试连接到我刚刚停止的节点,而不尝试连接到活动节点。
场景说明:
错误:连接ECONNREFUSED
具有IP1且不会故障转移到IP2(将其运行约20分钟,什么也没发生。如果有任何关联,则将DNS租约时间设置为5分钟)
如何为使用mqtt.js的应用程序使用DNS Round Robing实现故障转移? 感谢您的帮助
编辑:根据要求,添加了测试代码:
const mqtt = require('mqtt');
const tls = require('tls');
const MQTTTOPIC = 'test/upload';
const BROKER_URL = 'tls://mqtt.example.com';
const BROKER_PORT = '8883';
const MQTTUSER = 'username';
const MQTTPASS = 'password';
var mqttoptions = {
clientId: MQTTUSER,
port: BROKER_PORT,
keepalive: 60,
username: MQTTUSER,
password: MQTTPASS
};
var client = mqtt.connect(BROKER_URL, mqttoptions);
client.on('connect', mqtt_connect);
client.on('reconnect', mqtt_reconnect);
client.on('error', mqtt_error);
client.on('message', mqtt_messsageReceived);
client.on('close', mqtt_close);
function mqtt_connect() {
console.log("Connecting MQTT");
client.subscribe(MQTTTOPIC, mqtt_subscribe);
}
function mqtt_subscribe(err, granted) {
console.log("Subscribed to " + MQTTTOPIC);
if (err) { console.error(err); }
}
function mqtt_reconnect(err) {
console.log("Reconnect MQTT");
if (err) { console.error(err); }
client = mqtt.connect(BROKER_URL, mqttoptions);
}
function mqtt_error(err) {
console.error("MQTT Error!");
if (err) { console.error(err); }
}
function after_publish() {
//do nothing
}
function mqtt_close() {
console.warn("Close MQTT");
}
function mqtt_messsageReceived(topic, message, packet) {
console.log("Message: " + message + " --- Received on Topic " + topic);
}
编辑2: 万一重要,我将在pm2上运行代码
编辑3: 加上完整的日志输出:
17|LOCALTE | Connecting MQTT
17|LOCALTE | Subscribed to test/upload
17|LOCALTE | Close MQTT
17|LOCALTE | Reconnect MQTT
17|LOCALTE | Error: connect ECONNREFUSED IP1:8883
17|LOCALTE | at Object.exports._errnoException (util.js:1034:11)
17|LOCALTE | at exports._exceptionWithHostPort (util.js:1057:20)
17|LOCALTE | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1096:14)
17|LOCALTE | MQTT Error!
17|LOCALTE | { Error: connect ECONNREFUSED IP1:8883
17|LOCALTE | at Object.exports._errnoException (util.js:1034:11)
17|LOCALTE | at exports._exceptionWithHostPort (util.js:1057:20)
17|LOCALTE | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1096:14)
17|LOCALTE | code: 'ECONNREFUSED',
17|LOCALTE | errno: 'ECONNREFUSED',
17|LOCALTE | syscall: 'connect',
17|LOCALTE | address: 'IP1',
17|LOCALTE | port: 8883 }
17|LOCALTE | Close MQTT
17|LOCALTE | Reconnect MQTT
[...]
答案 0 :(得分:1)
首先,您不应该在connect()
回调中调用on.('reconnect')
。该库将为您处理所有这一切。
...
function mqtt_reconnect(err) {
console.log("Reconnect MQTT");
if (err) { console.error(err); }
}
...
如果将其删除后仍然无法使用,作为解决方法,您可以列出一组服务器,库将自行轮流运行。
var mqttoptions = {
clientId: MQTTUSER,
port: BROKER_PORT,
keepalive: 60,
username: MQTTUSER,
password: MQTTPASS
servers:[
{
protocol: 'mqtts',
host: 'ip-address-1',
port: 8883
},
{
protocol: 'mqtts',
host: 'ip-address-2',
port: 8883
}
]
}