我正在使用Nodejs cluster
模块来运行多个工作程序。
我创建了一个基本架构,其中将有一个MASTER进程,该进程基本上是一个处理多个请求的快速服务器,而MASTER的主要任务是将来自请求的传入数据写入REDIS实例。其他工作程序(numOfCPUs-1)将成为非主工作程序,即他们将不会处理任何请求,因为它们只是消费者。我有两个功能,即ABC和DEF。我通过为非主工作人员分配类型来平均分配他们。
例如:在8核计算机上:
1是通过快递服务器的MASTER实例处理请求
剩余(8-1 = 7)将平均分配。 4为特征:ABD,3为特征:DEF。
非主工人基本上是消费者,即他们从REDIS读取,只有主工人可以写入数据。
这是相同的代码:
if (cluster.isMaster) {
// Fork workers.
for (let i = 0; i < numCPUs - 1; i++) {
ClusteringUtil.forkNewClusterWithAutoTypeBalancing();
}
cluster.on('exit', function(worker) {
console.log(`Worker ${worker.process.pid}::type(${worker.type}) died`);
ClusteringUtil.removeWorkerFromList(worker.type);
ClusteringUtil.forkNewClusterWithAutoTypeBalancing();
});
// Start consuming on server-start
ABCConsumer.start();
DEFConsumer.start();
console.log(`Master running with process-id: ${process.pid}`);
} else {
console.log('CLUSTER type', cluster.worker.process.env.type, 'running on', process.pid);
if (
cluster.worker.process.env &&
cluster.worker.process.env.type &&
cluster.worker.process.env.type === ServerTypeEnum.EXPRESS
) {
// worker for handling requests
app.use(express.json());
...
}
{
除消费者从REDIS读取内容外,其他所有内容均正常运行。 由于特定功能有多个使用者,因此每个人都读取同一条消息并单独开始处理,这是我不想要的。如果有4个消费者,则1个被标记为忙碌,直到有空才能消费,有3个可用。一旦由MASTER将有关特定功能的消息写入REDIS,问题就出在该功能的所有3个可用使用者上。这意味着对于单个消息,将根据可用使用者的数量完成工作。
const stringifedData = JSON.stringify(req.body);
const key = uuidv1();
const asyncHsetRes = await asyncHset(type, key, stringifedData);
if (asyncHsetRes) {
await asyncRpush(FeatureKeyEnum.REDIS.ABC_MESSAGE_QUEUE, key);
res.send({ status: 'success', message: 'Added to processing queue' });
} else {
res.send({ error: 'failure', message: 'Something went wrong in adding to queue' });
}
消费者仅接受消息并在忙碌时停止
module.exports.startHeartbeat = startHeartbeat = async function(config = {}) {
if (!config || !config.type || !config.listKey) {
return;
}
heartbeatIntervalObj[config.type] = setInterval(async () => {
await asyncLindex(config.listKey, -1).then(async res => {
if (res) {
await getFreeWorkerAndDoJob(res, config);
stopHeartbeat(config);
}
});
}, HEARTBEAT_INTERVAL);
};
理想情况下,该特定功能的一个使用者只能阅读一条消息。消费后,它被标记为忙碌,因此直到有空(我已经处理了),它才进一步消耗。下一条消息只能由其他可用消费者中的一个消费者处理。
请帮助我解决这个问题。同样,我希望只有一位免费消费者才能阅读一条消息,其余的免费消费者应该等待新消息。
谢谢
答案 0 :(得分:1)
我不确定我是否完全了解您的Redis消费者体系结构,但是我觉得它与Redis本身的用例相矛盾。您想要实现的本质上是基于队列的消息传递,并且能够在消息完成后立即提交。
Redis具有其自己的pub / sub功能,但是它是基于即发即弃原则构建的。它不能区分使用者,它只是将数据发送给所有使用者,并假设其逻辑是处理传入数据。
我建议您使用RabbitMQ之类的队列服务器。您可以通过AMQP 0-9-1支持的某些功能来实现您的目标:消息确认,使用者的预取计数等。您可以使用非常敏捷的配置(例如 ok)设置集群,我想拥有X个使用者,每个使用者一次可以处理1条唯一的(!)消息,只有让服务器(rabbitmq)才会收到新消息)知道他们已经成功完成了邮件处理。这是高度可配置的且健壮的。
但是,如果您希望通过一些完全托管的服务而变得无服务器,以免调配虚拟机或其他任何东西来运行您选择的消息队列服务器,则可以使用AWS SQS。它具有非常相似的API和功能列表。
希望有帮助!