我确定这种问题已经在这里解决了很多次,但是我找不到这些问题的表达方式。
我有一个微服务,用于处理基础架构与MQTT Broker之间的通信。每次收到HTTP请求时,我都会发送“谁在房间XXX中还活着?”。 MQTT Broker上显示一条消息,并且每个在“ XXX / alive”主题上注册的客户端都必须回答,我等待Y毫秒,然后再通过将收到的响应发送回客户端来关闭请求。
当我处理一个请求时,它工作得很好。但是,一次要一个以上的请求时,它就搞砸了。
这是处理HTTP请求的Express路由:
app.get('/espPassports', (req, res) => {
mqttHelper.getESPPassports(req.query.model_Name).then((passports) => {
res.send(passports).end();
}).catch(err => {
res.send(err).end();
})
})
getESPPassports的工作原理如下:
getESPPassports: async (model_Name) => {
return new Promise((resolve, reject) => {
// Say there is a request performed
ongoing_request.isOpen = true;
ongoing_request.model_Name = model_Name;
// Ask who is alive
con.publish(topic, "ASK");
setTimeout(() => {
// If no answer after given timeout
if (ongoing_request.passports.length == 0) {
reject({ error: "No MQTT passports found" });
// Else send a deep clone of the answers (else it's empty)
} else {
resolve(JSON.parse(JSON.stringify(ongoing_request.passports)));
}
// Delete the current request object and 'close it'
ongoing_request.passports.length = 0;
ongoing_request.isOpen = false;
ongoing_request.model_Name = ""
}, process.env.mqtt_timeout || 2000)
})
}
};
这是MQTT侦听器:
con.on("message", (topic, message) => {
// If a passport is received check the topic and if there is a request opened
if (_checkTopic(topic) && ongoing_request.isOpen) {
try {
ongoing_request.passports.push(JSON.parse(message));
} catch (error) {
// do stuff if error
}
}
}
})
我知道问题出在我用来指定是否有正在进行的请求的布尔值中,我正在考虑为每个新请求创建一个对象,并通过唯一的ID(例如时间戳)来标识它们。无法使MQTT监听器知道此唯一ID。
我还有其他解决方案,但是我不确定它们是否会起作用,我觉得有一种方法可以很好地处理我不知道的问题。
祝你有美好的一天。
答案 0 :(得分:0)
您需要为每个请求生成一个唯一ID,并将其包含在MQTT消息中,然后可以缓存以该唯一ID作为键的Express响应对象。
设备需要在响应中包含唯一ID,以便将它们与正确的响应配对。
另一种方法是仅缓存来自设备的响应,并为缓存分配生存时间,因此您无需每次都询问设备。