Django-Celery异步的使用

一、前言

  Celery是一个基于python开发的分布式任务队列,而做python WEB开发最为流行的框架莫属Django,但是Django的请求处理过程都是同步的无法实现异步任务,若要实现异步任务处理需要通过其他方式(前端的一般解决方案是ajax操作),而后台Celery就是不错的选择。倘若一个用户在执行某些操作需要等待很久才返回,这大大降低了网站的吞吐量。下面将描述Django的请求处理大致流程(图片来源于网络):

请求过程简单说明:浏览器发起请求-->请求处理-->请求经过中间件-->路由映射-->视图处理业务逻辑-->响应请求(template或response)

1.快速入门

(本文以 Celery4.0 为基础进行书写)

首先,我们要理解 Celery 本身不是任务队列,它是管理分布式任务队列的工具,或者换一种说法,它封装好了操作常见任务队列的各种操作,我们用它可以快速进行任务队列的使用与管理,当然你也可以自己看 rabbitmq 等队列的文档然后自己实现相关操作都是没有问题的。

Celery 是语言无关的,虽然它是用 Python 实现的,但他提供了其他常见语言的接口支持。只是如果你恰好使用 Python 进行开发那么使用 Celery 就自然而然了。

想让 Celery 运行起来我们要明白几个概念:

1.1 Brokers

brokers 中文意思为中间人,在这里就是指任务队列本身,Celery 扮演生产者和消费者的角色,brokers 就是生产者和消费者存放/拿取产品的地方(队列)

常见的 brokers 有 rabbitmq、redis、Zookeeper 等

1.2 Result Stores / backend

顾名思义就是结果储存的地方,队列中的任务运行完后的结果或者状态需要被任务发送者知道,那么就需要一个地方储存这些结果,就是 Result Stores 了

常见的 backend 有 redis、Memcached 甚至常用的数据都可以。

1.3 Workers

就是 Celery 中的工作者,类似与生产/消费模型中的消费者,其从队列中取出任务并执行

1.4 Tasks

就是我们想在队列中进行的任务咯,一般由用户、触发器或其他操作将任务入队,然后交由 workers 进行处理。

理解以上概念后我们就可以快速实现一个队列的操作:

Django使用步骤:

1.安装‘中间人broker’,使用redis作为中间人,还可以使用RabbitMQ
    - pip install redis ---->redis版本不能太高不然会和Celery不匹配
    - pip install celery
    - pip install celery-with-redis
2.在settings.py中进行celery的配置
   
# celery配置
    CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'  # Broker配置,使用Redis作为消息中间件
​
    CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0'  # BACKEND配置,这里使用redis存储结果
​
    BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 3600}  # 链接超时
​
    # 可以接收的链接格式
    CELERY_ACCEPT_JSON = ['application/json', ]
​
    # 任务的序列化
    CELERY_TASK_SERIALIZER = 'json'
​
    # 结果序列化
    CELERY_RESULT_SERIALIZER = 'json'
​
    # celery时区  TIME_ZONE Django配置的时区
    CELERY_TIMEZONE = TIME_ZONE
3.在需要使用异步的app的目录中定义一个叫做task.py的文件
引入装饰器   from celery import @shared_task
​
#邮箱案例
@shared_task
def send_email_activate(username, receive, u_token):
​
    subject = '%s AXF Activate' % username
​
    from_email = EMAIL_HOST_USER
​
    recipient_list = [receive, ]
​
    data = {
        'username': username,
        'activate_url': 'http://{}:{}/axf/activate/?u_token={}'.format(SERVER_HOST, SERVER_PORT, u_token)
    }
​
    html_message = loader.get_template('user/activate.html').render(data)
​
    send_mail(subject=subject, message="", html_message=html_message, from_email=from_email, recipient_list=recipient_list)
4.启动异步celery
#注册
def register(request):
    if request.method == "GET":
​
        data = {
            "title": "注册"
        }
​
        return render(request, 'user/register.html', context=data)
    elif request.method == "POST":
​
        username = request.POST.get("username")
        email = request.POST.get("email")
        password = request.POST.get("password")
        icon = request.FILES.get("icon")
​
        # password = hash_str(password)
        password = make_password(password)
​
        user = AXFUser()
        user.u_username = username
        user.u_password = password
        user.u_email = email
        user.u_icon = icon
        user.save()
​
        u_token = uuid.uuid4().hex
​
        cache.set(u_token, user.id, timeout=60 * 60 * 24)
        # 启动异步.delay
        send_email_activate.delay(username, email, u_token)
        return redirect(reverse('axf:login'))
5.配置celery作为一个单独的线程,帮助用户异步发送邮件
    A: 在项目同名文件夹下新建一个celery.py文件(目的:加载settings.py中配置信息给celery对象)
        from __future__ import absolute_import, unicode_literals
        import os
        from celery import Celery
​
​
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gits.settings')  # 设置django环境
​
        app = Celery('gits')
​
        #  使用CELERY_ 作为前缀,在settings中写配置
        app.config_from_object('django.conf:settings', namespace='CELERY')
​
​
        # 发现任务文件每个app下的task.py
        app.autodiscover_tasks()
    B:在项目同名文件夹下init.py中添加
        from __future__ import absolute_import, unicode_literals
        '''
        absolute_import绝对导入:
        如果当前项目由一个sys.py,我用的时候总会调用系统的sys.py。
        如果当前目录和sys.path的路径中都有一个foo,则会调用当前目录下的foo。
        
        unicode_literrals:
        对字符串使用unicode字符
        '''
        # 导入刚才配置的celery_app对象
        from .celery import app as celery_app
        __all__ = ['celery_app']
6.测试启动异步
 启动异步worker
    celery beat启动命令: celery -A  项目名 beat -l info
    Redis服务端启动命令 redis-server 

 

 

 

posted @ 2020-12-11 15:47  IT小码农!!!!  阅读(285)  评论(0)    收藏  举报