Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 布尔队列并发问题_Javascript_Node.js_Concurrency_Bull.js - Fatal编程技术网

Javascript 布尔队列并发问题

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

我需要帮助了解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 something...});
这是否意味着在所有10个节点实例中,最多有5个(并发)并发运行
jobTypeA
类型的作业?还是我误解了,并发设置是每个节点实例

如果一个节点实例指定了不同的并发值,会发生什么情况


我可以确定作业不会由多个节点实例处理吗?

啊,欢迎!这是一个元答案,可能不是你所希望的,而是解决这个问题的一般过程:

  • 非常仔细地确定您的解决方案旨在提供哪些保证:
您可以指定并发参数。公牛会叫你的狗 与此最大值相关的并行处理程序

我个人并不真正理解这一点,也不理解bull提供的保证。因为它不是非常清晰:

  • 深入了解源代码以更好地了解实际发生的情况。我通常只是通过追踪路径来理解:

    • 。。。更多这是相当大的:p
  • 如果提供的实现和保证仍然不明确,那么创建测试用例来尝试并使假设无效,这听起来像:

    • 为具有2个不同并发值的同一队列初始化进程
    • 创建一个队列和两个辅助进程,将并发级别设置为1,并创建一个回调,记录消息进程,然后在每个辅助进程上超时,将2个事件排入队列,并观察这两个事件是并发处理还是限制为1
在国际海事组织,最大的问题是:

我是否可以确定作业不会由多个节点处理 实例


如果独占消息处理是不变的,并且会导致您的应用程序不正确,即使有很好的文档,我强烈建议您对库进行尽职调查:p

进一步研究,我认为Bull根本无法处理跨多个节点实例分布的问题,因此,行为充其量是未定义的。

TL;DR is:在正常情况下,作业只处理一次。如果出现问题(比如Node.js进程崩溃),作业可能会被双重处理

引用公牛队官员的话:

重要注意事项 队列的目标是“至少一次”工作策略。这意味着在某些情况下,可以多次处理作业。这通常发生在工人在整个处理过程中未能为给定作业保持锁的情况下

当工作人员处理作业时,它将保持该作业“锁定”,以便其他工作人员无法处理该作业

重要的是要了解锁定是如何工作的,以防止您的作业失去锁定—停止—并因此重新启动。通过在间隔
LockRenewalTime
上为
lockDuration
创建一个锁(通常为
lockDuration
的一半),可以在内部实现锁定。如果
lockDuration
在更新锁之前过期,则作业将被视为已暂停并自动重新启动;它将被双重处理。这可能发生在以下情况:

  • 运行作业处理器的节点进程意外终止
  • 您的作业处理器过于CPU密集,导致节点事件循环暂停,因此,Bull无法更新作业锁(请参阅#488了解如何更好地检测此问题)。您可以通过将作业处理器拆分为更小的部分来解决此问题,这样就没有单个部分可以阻止节点事件循环。或者,您可以为lockDuration设置传递更大的值(折衷是,识别真正暂停的作业需要更长的时间)
  • 因此,您应该始终侦听
    stalled
    事件,并将其记录到错误监控系统中,因为这意味着您的作业可能会被双重处理

    作为一种保护措施,有问题的作业不会无限期地重新启动(例如,如果作业处理器总是使其节点进程崩溃),作业将从暂停状态恢复最多
    maxStalledCount
    次(默认值:
    1


    我花了很多时间来研究它,因为我面对的是现实

    简而言之,bull的并发性是在队列对象级别,而不是队列级别

    如果深入研究代码,将在对队列对象调用
    .process
    时调用并发设置。这意味着,即使在同一节点应用程序中,如果创建多个队列并多次调用
    .process
    ,它们也会增加可处理的并发作业数

    一名撰稿人发表了以下评论:

    是的,当我第一次使用Bull时,我也有点惊讶 时间队列选项永远不会在Redis中持久化。你可以有很多 根据需要为每个应用程序排队实例,每个实例可以有不同的 设置。并发设置是在注册时设置的 事实上,它特定于每个process()函数调用,而不是 队列如果使用命名处理器,可以多次调用process() 时代。每个调用将注册N个事件循环处理程序(使用节点的 process.nextTick()),按并发量(默认值为1)


    因此,您的问题的答案是:是的,如果您在多个节点实例中注册进程处理程序,您的进程将由多个节点实例处理。

    Bull设计用于同时处理具有“至少一次”语义的作业,但如果处理器工作正常,即没有暂停或崩溃,事实上,它正在“准确地传递一次”。但是,您可以将最大暂停重试次数设置为0(maxStalledCount),然后再设置sema