celery任务队列使用

celery任务队列使用

  • 项目架构

    .
    ├── broker
    │   ├── __init__.py
    │   ├── cron.py
    │   └── req.py
    ├── config
    │   ├── __init__.py
    │   ├── dev.py
    │   └── prod.py
    ├── task
    │   ├── __init__.py
    │   ├── base.py
    │   ├── cron
    │   │   ├── __init__.py
    │   │   └── check.py
    │   └── req
    │       ├── __init__.py
    │       └── waste_task.py
    ├── main.py
    └── requirements.txt
    
  • 依赖包

    amqp               2.6.1
    billiard           3.6.4.0
    celery             4.4.0
    certifi            2021.10.8
    charset-normalizer 2.0.7
    idna               3.3
    importlib-metadata 4.8.2
    kombu              4.6.11
    pip                21.2.4
    pytz               2021.3
    redis              3.5.3
    requests           2.26.0
    setuptools         58.2.0
    typing-extensions  3.10.0.2
    urllib3            1.26.7
    vine               1.3.0
    wheel              0.37.0
    zipp               3.6.0
    
  • 配置

    # -*- coding=utf-8 -*-
    
    # 文件所在位置 : config/dev.py
    
    from datetime import timedelta
    # 公共配置
    COMMON_CONFIG = {
        "CELERYD_CONCURRENCY": 2,
        "CELERYD_MAX_TASKS_PER_CHILD": 10,
        "CELERYD_HIJACK_ROOT_LOGGER": True,
        "CELERY_ANNOTATIONS": {
            '*': {'rate_limit': '10/s'}
        }
    }
    
    # 任务队列配置
    REQ_CONFIG = {
        "BROKER_URL": 'redis://:123456@127.0.0.1:6379/1',
        "RESULTS_BACKEND ": 'redis://:123456@127.0.0.1:6379/2',
        "CELERY_IMPORTS": [
            'task.req.waste_task',
        ]
    }
    
    # 定时配置(定义简单版)
    CRON_CONFIG = {
        "BROKER_URL": 'redis://:123456@127.0.0.1:6379/3',
        "CELERY_DEFAULT_QUEUE": "default",
        "CELERY_IMPORTS": [
            'task.cron.check'
        ],
        'CELERYBEAT_SCHEDULE': {
            'check_product': {
                'task': 'task.cron.check.test_1',
                'schedule': timedelta(seconds=6), # 每6s执行一次
                'args': () # 执行参数
            },
            'test_2': {
                'task': 'task.cron.check.test_2',
                'schedule': timedelta(seconds=10), # 每10s执行一次
                'args': () # 执行参数
            },
            'test_3': {
                'task': 'task.cron.check.test_3',
                'schedule': timedelta(seconds=20), # 每20s执行一次
                'args': () # 执行参数
            }
        }
    }
    
    # 定义请求任务队列配置和定时任务队列
    REQ_CONFIG.update(COMMON_CONFIG)
    CRON_CONFIG.update(COMMON_CONFIG)
    
  • 自定义任务基类

    # -*- coding=utf-8 -*-
    
    # 文件所在位置 : task/base.py
    
    from celery import Task
    
    # 任务基类
    class BaseTask(Task):
        # 成功时回调,只能证明此任务执行成功,不代表程序逻辑一定成功
        def on_success(self, retval, task_id, args, kwargs):
            print("任务成功")
            return super(BaseTask, self).on_success(retval, task_id, args, kwargs)
    
        # 失败回调, 当重试结束后或者直接失败,则会触发此方法
        def on_failure(self, exc, task_id, args, kwargs, einfo):
            print("任务失败")
            return super(BaseTask, self).on_failure(exc, task_id, args, kwargs, einfo)
    
        # 任务重试, 到最后一次重试后会走到失败回调,前端需要使用 self.retry() 方法触发
        def on_retry(self, exc, task_id, args, kwargs, einfo):
            print("重试")
            print(args)
            print(kwargs)
            super(BaseTask, self).on_retry(exc, task_id, args, kwargs, einfo)
    
        # 任务执行成功并返回内容,可以根据内容来判定是否是一次有效的执行任务
        def after_return(self, status, retval, task_id, args, kwargs, einfo):
            print(retval)
            super(BaseTask, self).after_return(status, retval, task_id, args, kwargs, einfo)
    
  • 代理人

    • 请求任务

      # -*- coding=utf-8 -*-
      
      # 文件所在位置 : broker/req.py
      
      from celery import Celery
      from config import REQ_CONFIG
      
      # 实例化任务队列
      req = Celery(
          "req" # 自定义队列名称
      )
      
      # 导入配置
      req.config_from_object(REQ_CONFIG)
      
    • 定时任务

      # -*- coding=utf-8 -*-
      
      # 文件所在位置 : broker/cron.py
      
      from celery import Celery
      from config import CRON_CONFIG
      cron = Celery(
          "cron" # 自定义实例名称
      )
      # 导入配置
      cron.config_from_object(CRON_CONFIG)
      
  • 任务

    • 请求任务

      # -*- coding=utf-8 -*-
      
      # 文件所在位置 : task/req.py
      
      from broker.req import req
      import requests
      from task.base import BaseTask
      
      
      @req.task(bind=True)
      def waste_task_1(self, x, y):
          return x * y
      
      @req.task(bind=True,base=BaseTask)
      def waste_task_2(self, id, url):
          try:
              resp = requests.get(url, timeout=2)
          except:
              self.retry(max_retries=3, countdown=5)
          return resp
      
    • 定时任务

      # -*- coding=utf-8 -*-
      
      # 文件所在位置 : task/cron.py
      
      from broker.cron import cron
      from task.base import BaseTask
      import time
      
      @cron.task(bind=True)
      def test_1(self):
          print("定时 test_1 : %s"%(time.time()))
      
      @cron.task(bind=True, base=BaseTask)
      def test_2(self):
          try:
              1 / 0
          except:
              self.retry(countdown=10, max_retries=5)
      
      @cron.task(bind=True, base=BaseTask)
      def test_3(self):
          try:
              print("定时 test_3 : %s"%(time.time()))
          except:
              self.retry(countdown=10, max_retries=5)
      
  • 启动任务

    • 启动请求任务

      celery -A broker.req worker --loglevel=info --logfile="xxx/req_task.log" &
      
    • 启动定时任务

      celery -A broker.cron beat
      celery -A broker.cron worker --loglevel=info --logfile="xxx/cron_task.log" &
      
  • 使用

    • 定时任务,已经自行启动并运行,所以不需要关注。

    • 请求任务,伪代码如下:

      # -*- coding=utf-8 -*-
      
      # 文件所在位置 : main.py
      
      from task.waste_task import waste_task_1, waste_task_2
      def test1():
          x, y = 10, 20
      	waste_task_1.delay(x, y)
      def test2():
          id, url = 100, "https://baidu.com"
          waste_task_2.delay(id, url)
      
posted @ 2021-11-09 12:00  巫小诗  阅读(140)  评论(0编辑  收藏  举报