celery

文章参考:https://mp.weixin.qq.com/s/lXrp3igYo9W2UuE5Gauysg

概要

  • celery,处理任务的Python的模块。

    • 场景1:

      对【耗时的任务】,通过celery,将任务添加到broker(队列),然后立即给用户返回一个任务ID。
      当任务添加到broker之后,由worker去broker获取任务并处理任务。
      任务弯完成之后,再将结果放到backend中
      
      用户想要检查结果,提供任务ID,我们就可以去backend中去帮他查找。
      
    • 场景2:

      定时任务(定时发布/定时拍卖)
      

详细

1.celery

celery是一个基于Python开发的模块,可以帮助我们对任务进行分发和处理。

1.1 环境的搭建

pip3 install celery==4.4
安装broker: redis或rabbitMQ
pip3 install redis / pika

1.2 快速使用

  • s1.py

    from celery import Celery
    
    app = Celery('tasks', broker='redis://127.0.0.1:6379', backend='redis://127.0.0.1:6379')
    
    @app.task
    def x1(x, y):
        return x + y
    
    @app.task
    def x2(x, y):
        return x - y
    
  • s2.py

    from s1 import x1
    
    result = x1.delay(4, 4) #任务添加到broker(队列)
    print(result.id)
    
  • s3.py

    from celery.result import AsyncResult
    from s1 import app
    
    result_object = AsyncResult(id="任务ID", app=app) #提交任务ID,去backend查找
    print(result_object.status)
    

运行程序:

  1. 启动redis

  2. 启动worker

    linux:
    # 进入当前目录
    celery worker -A s1 -l info
    
    windows:
    
    pip install eventlet
    #执行:
    celery worker -A s1 -l info -P eventlet
    celery -A zhibo worker -l info --pool=solo(如果报错,尝试使用此命令启动)
    
  3. 创建任务

    python s2.py
    python s2.py
    
  4. 查看任务状态

    # 填写任务ID
    ptyhon s3.py 
    

1.3 django中应用celery

之后,需要按照django-celery的要求进行编写代码。

  • 第一步:【项目/项目/settings.py 】添加配置

    CELERY_BROKER_URL = 'redis://192.168.16.85:6379'
    CELERY_ACCEPT_CONTENT = ['json']
    CELERY_RESULT_BACKEND = 'redis://192.168.16.85:6379'
    CELERY_TASK_SERIALIZER = 'json'
    
  • 第二步:【项目/项目/celery.py】在项目同名目录创建 celery.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import os
    from celery import Celery
    
    # set the default Django settings module for the 'celery' program.
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'demos.settings')
    
    app = Celery('demos')
    
    # Using a string here means the worker doesn't have to serialize
    # the configuration object to child processes.
    # - namespace='CELERY' means all celery-related configuration keys
    #   should have a `CELERY_` prefix.
    app.config_from_object('django.conf:settings', namespace='CELERY')
    
    # Load task modules from all registered Django app configs.
    # 去每个已注册app中读取 tasks.py 文件
    app.autodiscover_tasks()
    
  • 第三步,【项目/app名称/tasks.py】

    from celery import shared_task
    
    @shared_task
    def add(x, y):
        return x + y
    
    @shared_task
    def mul(x, y):
        return x * y
    
  • 第四步,【项目/项目/__init__.py

    from .celery import app as celery_app
    
    __all__ = ('celery_app',)
    
  • 启动worker

    进入项目目录
    
    celery worker -A demos -l info -P eventlet (windows)
    celery -A website worker -l info (Linux)
    
  • 编写视图函数,调用celery去创建任务。

    • url

      url(r'^create/task/$', task.create_task),
      url(r'^get/result/$', task.get_result),
      
    • 视图函数

      from django.shortcuts import HttpResponse
      from api.tasks import x1
      
      def create_task(request):
          print('请求来了')
          result = x1.delay(2,2)
          print('执行完毕')
          return HttpResponse(result.id)
      
      
      def get_result(request):
          nid = request.GET.get('nid')
          from celery.result import AsyncResult
          # from demos.celery import app
          from demos import celery_app
          result_object = AsyncResult(id=nid, app=celery_app)
          # print(result_object.status)
          data = result_object.get()
          return HttpResponse(data)
      
  • 启动django程序

    python manage.py ....
    

1.4 celery定时执行

def create_task(request):
    # # 1 耗时任务(立即执行)
    # result = tasks.add.delay(2, 8)
    # print(result.id)

    # 2 延时任务(需要转化为utc时间)
    ctime = datetime.datetime.now() # --datetime.datetime(2021, 3, 12, 3, 2, 12, 999416)
    utc_ctime = datetime.datetime.utcfromtimestamp(ctime.timestamp()) # utc时间
    s10 = datetime.timedelta(seconds=10)
    ctime_x = utc_ctime + s10
    # 使用apply_async并设定时间
    result =tasks.add.apply_async(args=[1, 3], eta=ctime_x)

    print(result.id)
    return HttpResponse('交给broker队列中,让celery去执行')



def get_result(request):
    task_id = request.GET.get('nid')
    print(task_id)
    result_object = AsyncResult(id=task_id, app=celery_app)
    # print(result_object.status)  # 获取状态
    # print(result_object.get())  # 获取数据
    # result_object.forget() # 将数据在backend中移除
    # result_object.revoke() # 取消任务
    # 使用模板
    if result_object.successful():
        data = result_object.get()
        result_object.forget()
        print('成功', data)
    elif result_object.failed():
        pass
    else:
        pass

    return HttpResponse('celery。。。')

1.5 周期性定时任务

  • celery
  • django中也可以结合使用

1 website/celery.py文件添加如下配置以支持定时任务crontab

from celery.schedules import crontab
app.conf.update(
    CELERYBEAT_SCHEDULE = {
        'sum-task': {
            'task': 'deploy.tasks.add',
            'schedule':  timedelta(seconds=20),
            'args': (5, 6)
        }
        'send-report': {
            'task': 'deploy.tasks.report',
            'schedule': crontab(hour=4, minute=30, day_of_week=1),
        }
    }
)

--定义了两个task:

1 名字为'sum-task'的task,每20秒执行一次add函数,并传了两个参数5和6

2 名字为'send-report'的task,每周一早上4:30执行report函数

--timedelta是datetime中的一个对象,需要from datetime import timedelta引
入,有如下几个参数
days:天
seconds:秒
microseconds:微妙
milliseconds:毫秒
minutes:分
hours:小时
crontab的参数有:
month_of_year:月份
day_of_month:日期
day_of_week:周
hour:小时
minute:分钟

1.deploy/tasks.py文件添加report方法:

@shared_task
def report():
    return 5

2.启动celery beat,celery启动了一个beat进程一直在不断的判断是否有任务需要执行

celery -A website beat -l info

tips
1 如果同时使用异步任务和计划任务,有一种更简单的启动方式
celery -A website worker -b -l info,可同时启动worker和beat

2 如果使用的不是rabbitmq做队列那么需要在主配置文件中website/celery.py配置broker和backend,如下:
redis做MQ配置

app = Celery('website', backend='redis', broker='redis://localhost')

rabbitmq做MQ配置

app = Celery('website', backend='amqp', broker='amqp://admin:admin@localhost')

3 celery不能用root用户启动的话需要在主配置文件中添加platforms.C_FORCE_ROOT = True
4 celery在长时间运行后可能出现内存泄漏,需要添加配置CELERYD_MAX_TASKS_PER_CHILD = 10,表示每个worker执行了多少个任务就死掉`

celery_django_demo点击下载

1.6 监控-管理工具

官网链接:https://docs.celeryproject.org/en/stable/userguide/monitoring.html#flower-real-time-celery-web-monitor

Flower 是一个基于 Web 的实时监控和 Celery 管理工具

命令:
celery -A meanning_server flower -l info --basic_auth=admin:meanning0 --port=5555

访问:http://localhost:5555

posted @ 2021-05-26 15:07  风hua  阅读(274)  评论(3编辑  收藏  举报