Javascript 布尔队列并发问题
我需要帮助了解Bull Queue(Bull.js)如何处理并发作业 假设我有10个Node.js实例,每个实例实例化一个连接到同一Redis实例的Bull队列:Javascript 布尔队列并发问题,javascript,node.js,concurrency,bull.js,Javascript,Node.js,Concurrency,Bull.js,我需要帮助了解Bull Queue(Bull.js)如何处理并发作业 假设我有10个Node.js实例,每个实例实例化一个连接到同一Redis实例的Bull队列: const bullQueue = require('bull'); const queue = new bullQueue('taskqueue', {...}) const concurrency = 5; queue.process('jobTypeA', concurrency, job => {...do someth
const bullQueue = require('bull');
const queue = new bullQueue('taskqueue', {...})
const concurrency = 5;
queue.process('jobTypeA', concurrency, job => {...do something...});
这是否意味着在所有10个节点实例中,最多有5个(并发)并发运行jobTypeA
类型的作业?还是我误解了,并发设置是每个节点实例
如果一个节点实例指定了不同的并发值,会发生什么情况
我可以确定作业不会由多个节点实例处理吗?啊,欢迎!这是一个元答案,可能不是你所希望的,而是解决这个问题的一般过程:
- 非常仔细地确定您的解决方案旨在提供哪些保证:
- 深入了解源代码以更好地了解实际发生的情况。我通常只是通过追踪路径来理解:
- 。。。更多这是相当大的:p
- 如果提供的实现和保证仍然不明确,那么创建测试用例来尝试并使假设无效,这听起来像:
- 为具有2个不同并发值的同一队列初始化进程
- 创建一个队列和两个辅助进程,将并发级别设置为1,并创建一个回调,记录消息进程,然后在每个辅助进程上超时,将2个事件排入队列,并观察这两个事件是并发处理还是限制为1
如果独占消息处理是不变的,并且会导致您的应用程序不正确,即使有很好的文档,我强烈建议您对库进行尽职调查:p进一步研究,我认为Bull根本无法处理跨多个节点实例分布的问题,因此,行为充其量是未定义的。TL;DR is:在正常情况下,作业只处理一次。如果出现问题(比如Node.js进程崩溃),作业可能会被双重处理 引用公牛队官员的话: 重要注意事项 队列的目标是“至少一次”工作策略。这意味着在某些情况下,可以多次处理作业。这通常发生在工人在整个处理过程中未能为给定作业保持锁的情况下 当工作人员处理作业时,它将保持该作业“锁定”,以便其他工作人员无法处理该作业 重要的是要了解锁定是如何工作的,以防止您的作业失去锁定—停止—并因此重新启动。通过在间隔
LockRenewalTime
上为lockDuration
创建一个锁(通常为lockDuration
的一半),可以在内部实现锁定。如果lockDuration
在更新锁之前过期,则作业将被视为已暂停并自动重新启动;它将被双重处理。这可能发生在以下情况:
stalled
事件,并将其记录到错误监控系统中,因为这意味着您的作业可能会被双重处理
作为一种保护措施,有问题的作业不会无限期地重新启动(例如,如果作业处理器总是使其节点进程崩溃),作业将从暂停状态恢复最多maxStalledCount
次(默认值:1
)
我花了很多时间来研究它,因为我面对的是现实 简而言之,bull的并发性是在队列对象级别,而不是队列级别 如果深入研究代码,将在对队列对象调用
.process
时调用并发设置。这意味着,即使在同一节点应用程序中,如果创建多个队列并多次调用.process
,它们也会增加可处理的并发作业数
一名撰稿人发表了以下评论:
是的,当我第一次使用Bull时,我也有点惊讶
时间队列选项永远不会在Redis中持久化。你可以有很多
根据需要为每个应用程序排队实例,每个实例可以有不同的
设置。并发设置是在注册时设置的
事实上,它特定于每个process()函数调用,而不是
队列如果使用命名处理器,可以多次调用process()
时代。每个调用将注册N个事件循环处理程序(使用节点的
process.nextTick()),按并发量(默认值为1)
因此,您的问题的答案是:是的,如果您在多个节点实例中注册进程处理程序,您的进程将由多个节点实例处理。Bull设计用于同时处理具有“至少一次”语义的作业,但如果处理器工作正常,即没有暂停或崩溃,事实上,它正在“准确地传递一次”。但是,您可以将最大暂停重试次数设置为0(maxStalledCount),然后再设置sema