近期在项目中遇到celery任务排队处理的问题
1、任务多 消费不及时
2、有些需要紧急消费的 也在排队 无法插队
针对以上情况。进行了如下处理
1、首先建立优先级队列 实现消费优先级 ,即针对Queue 进行设置:x-max-priority 。数字越大 优先级越高,建议范围值 1-10.
2、同一队列实现任务优先级 ,即在发送任务的时候 增加参数 priority 即可
下面的可以直接运行 启动celery的时候 可以增加多个work
# !coding:utf-8
import time
from celery import Celery
from celery.exceptions import TimeoutError
from celery.result import AsyncResult, GroupResult
from kombu import Queue, Exchange
from celery.signals import after_task_publish, celeryd_after_setup, after_setup_logger, task_received, task_success
from celery.utils.log import get_logger, worker_logger
from celery import chain, group, chord, chunks
import logging
# celery配置,4.0之后引入了小写配置,这种大写配置在6.0之后将不再反对
# 能够参考此链接
# https://docs.celeryproject.org/en/stable/userguide/configuration.html?highlight=worker#std-setting-enable_utc
CONFIG = {
# 设置时区
'CELERY_TIMEZONE': 'Asia/Shanghai',
# 默认为true,UTC时区
'CELERY_ENABLE_UTC': False,
# broker,rabbitMQ的VHOST要给你应用的用户加权限
'BROKER_URL': 'amqp://root:root@127.0.0.1:5672/test',
# backend配置,指定redis数据库
# 'CELERY_RESULT_BACKEND': 'redis://127.0.0.1:30412/4',
# worker最大并发数
'CELERYD_CONCURRENCY': 10,
# 如果不设置,默认是celery队列,此处应用默认的直连交换机,routing_key完全一致才会调度到celery_demo队列
'CELERY_ACKS_LATE': True,
'CELERYD_PREFETCH_MULTIPLIER': 1,
#注意:元组中只有一个值的话,须要最初加逗号
'CELERY_QUEUES': (
Queue("celery_high", Exchange("celery_high"), routing_key="celery_high",
queue_arguments={'x-max-priority': 10}),
Queue("celery", Exchange("celery"), routing_key="celery", queue_arguments={'x-max-priority': 5}),
)
}
app = Celery()
app.config_from_object(CONFIG)
@app.task(name='demo_task')
def demo_task(x, y):
print("当前低优先级:{} * {}={}".format(x, y, x * y))
time.sleep(5)
return True
@app.task(name='demo_task2')
def demo_task2(x, y):
print("当前高优先级:{} * {}={}".format(x, y, x * y))
return True
def call():
for _ in range(30):
demo_task.apply_async((_, _), routing_key='celery', queue='celery')
def priority_call():
time.sleep(30)
print("再以优先级由低到高的程序下发10个工作,预期工作将逆序执行")
for _ in range(30, 40):
# apply_async提供priority参数指定优先级
demo_task2.apply_async((_, _), routing_key='celery_high', queue='celery_high', priority=_ % 10)
if __name__ == '__main__':
call()
if __name__ == '__main__':
priority_call()