我的Node应用程序使用Mongo更改流,并且该应用程序在生产环境中运行3个以上的实例(最终,因此,随着它的增长,这将成为一个更大的问题)。因此,当发生更改时,更改流功能将运行的次数与进程的次数相同。
如何进行设置,使更改流仅运行一次?
这就是我所拥有的:
const options = { fullDocument: "updateLookup" };
const filter = [
{
$match: {
$and: [
{ "updateDescription.updatedFields.sites": { $exists: true } },
{ operationType: "update" }
]
}
}
];
const sitesStream = Client.watch(sitesFilter, options);
// Start listening to site stream
sitesStream.on("change", async change => {
console.log("in site change stream", change);
console.log(
"in site change stream, update desc",
change.updateDescription
);
// Do work...
console.log("site change stream done.");
return;
});
答案 0 :(得分:1)
虽然Kafka选项听起来很有趣,但是在我不熟悉的平台上进行了很多基础架构工作,所以我决定在离我较近的地方走一段路,向一个小摊位发送MQTT消息。一个单独的应用程序,然后让MQTT服务器监视消息的唯一性。
siteStream.on("change", async change => {
console.log("in site change stream);
const mqttClient = mqtt.connect("mqtt://localhost:1883");
const id = JSON.stringify(change._id._data);
// You'll want to push more than just the change stream id obviously...
mqttClient.on("connect", function() {
mqttClient.publish("myTopic", id);
mqttClient.end();
});
});
我仍在研究MQTT服务器的最终版本,但是评估消息唯一性的方法可能会在应用程序内存中存储更改流ID的数组,因为不需要持久保存它们,并评估是否根据之前是否已经看到过更改流ID来进行任何进一步的操作。
var mqtt = require("mqtt");
var client = mqtt.connect("mqtt://localhost:1883");
var seen = [];
client.on("connect", function() {
client.subscribe("myTopic");
});
client.on("message", function(topic, message) {
context = message.toString().replace(/"/g, "");
if (seen.indexOf(context) < 0) {
seen.push(context);
// Do stuff
}
});
这不包括安全性等,但是您知道了。
答案 1 :(得分:1)
仅使用Mongodb查询运算符就可以轻松完成。您可以在ID字段上添加模查询,其中除数是您的应用实例数(N)。余数则为元素{0,1,2,...,N-1}。如果您的应用实例从零到N-1升序编号,则可以这样编写过滤器:
yield (k, flatten_json(v))
答案 2 :(得分:1)
要做到这一点很困难,但并非没有可能。我在这里写了一种解决方案的详细信息:requests
示例是用Java编写的,但重要的部分是算法。
这归结为一些技巧:
fencing token中的更多详细信息。
答案 3 :(得分:0)
听起来您需要一种在实例之间划分更新的方法。您是否研究过Apache Kafka?基本上,您会做的是只有一个应用程序,将更改数据写入分区的Kafka主题,并使您的节点应用程序成为Kafka使用者。这样可以确保只有一个应用程序实例会收到更新。
根据您的分区策略,您甚至可以确保同一记录的更新始终转到同一节点应用程序(如果您的应用程序需要保持自己的状态)。否则,您可以循环方式散布更新。
使用Kafka的最大好处是您可以添加和删除实例,而无需调整配置。例如,您可以启动一个实例,它将处理所有更新。然后,一旦您启动另一个实例,它们各自就开始处理一半的负载。您可以在有分区的任意多个实例上继续使用此模式(如果需要,可以将主题配置为具有1000个分区),这就是Kafka用户组的力量。按比例缩小则相反。
答案 4 :(得分:-1)
将在数据库中有一个名为status
的字段,该字段将根据从变更流接收到的事件使用findAnUpdate进行更新。因此,可以说您从变更流中同时获得2个事件。第一个事件会将状态更新为start
,如果状态为start
,则另一个事件将引发错误。因此,第二个事件将不会处理任何业务逻辑。