阻止芹菜工人从所有队列消费

时间:2016-07-11 10:22:30

标签: python multithreading celery

干杯,

我有一个在生产环境(在Linux上)运行的芹菜设置,我需要从两个专用队列(每个队列一个)中使用两种不同的任务类型。出现的问题是,所有工作人员总是绑定到两个队列,即使我指定他们只使用其中一个队列。

TL; DR

  • 芹菜以2个队列运行
  • 消息按设计正确排队发布
  • 工人继续消耗两个队列
  • 导致死锁

一般资料

将我的两种不同任务类型视为分层设置:

  • 任务是一项常规的芹菜任务,可能需要相当长的时间,因为它动态调度其他芹菜任务,可能需要链接各自的结果

  • 节点是一个动态调度的子任务,它也是一个常规的芹菜任务,但它本身可以被视为原子单位。

我的任务因此可以是节点的更复杂的设置,其中一个或多个节点的结果用作一个或多个后续节点的输入,依此类推。由于我的任务可能需要更长的时间,并且只有在部署了所有节点后才能完成,因此必需是专门处理的工人保持足够数量的工人可以自由使用节点。否则,当调度了很多任务时,这可能导致系统卡住,每个任务由另一个工作人员消耗,并且他们各自的节点仅排队但会从不被消费,因为所有工人都被封锁了。

如果这通常是一个糟糕的设计,请就如何改进它提出任何建议。我还没有设法使用芹菜的内置画布原语构建其中一个进程。如果可以,请帮帮我?!

配置/设置

我用amqp运行芹菜,并在芹菜配置中设置了以下队列和路由:

CELERY_QUERUES = (
    Queue('prod_nodes', Exchange('prod'), routing_key='prod.node'),
    Queue('prod_tasks', Exchange('prod'), routing_key='prod.task')
)

CELERY_ROUTES = (
    'deploy_node': {'queue': 'prod_nodes', 'routing_key': 'prod.node'},
    'deploy_task': {'queue': 'prod_tasks', 'routing_key': 'prod.task'}
)

当我启动工作人员时,我发出类似以下的电话:

celery multi start w_task_01 w_node_01 w_node_02 -A my.deployment.system \
  -E -l INFO -P gevent -Q:1 prod_tasks -Q:2-3 prod_nodes -c 4 --autoreload \
  --logfile=/my/path/to/log/%N.log --pidfile=/my/path/to/pid/%N.pid

问题

我的队列和路由设置似乎工作正常,因为我可以看到消息在 RabbitMQ Management Web UI中正确排队。

但是,所有工作人员总是从两个队列中消耗芹菜任务。当我启动并打开 flower Web UI并检查其中一个已部署的任务时,我可以看到这一点,例如, w_node_01 开始使用来自 prod_tasks 队列的消息,即使它不应该。

RabbitMQ管理 Web UI还告诉我,所有已启动的工作人员都被设置为两个队列的使用者

因此,我问你......

......我做错了什么?

我的设置或工作人员开始调用的问题在哪里;如何规避工人总是在两个队列中消费的问题;我是否真的必须在运行期间进行其他设置(我当然不想要)?

感谢您的时间和答案!

2 个答案:

答案 0 :(得分:1)

You can create 2 separate workers for each queue and each one's define what queue it should get tasks from using the -Q command line argument.

If you want to keep the number processes the same, by default a process is opened for each core for each worker you can use the --concurrency flag (See Celery docs for more info)

答案 1 :(得分:0)

Celery允许为具有特定队列的工作人员配置。

1)使用' queue'指定队列的名称。不同类型工作的属性

celery.send_task('job_type1', args=[], kwargs={}, queue='queue_name_1')
celery.send_task('job_type2', args=[], kwargs={}, queue='queue_name_2')

2)在配置文件中添加以下条目

CELERY_CREATE_MISSING_QUEUES = True

3)启动工作人员时,传递-Q' queue_name'作为参数,用于从所需队列中消费。

celery -A proj worker -l info -Q queue_name_1 -n worker1
celery -A proj worker -l info -Q queue_name_2 -n worker2