用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作

大家好,这是皮爷给大家带来的最新的学习Python能干啥?之Django教程的进阶版

在之前《用Django全栈开发》系列专辑里面,皮爷详细的阐述了如何编写一个完整的网站,具体效果可以在代码中获取到。

从进阶篇开始,每一篇文章都是干货满满,干的不行。这一节,我们来说:如何使用Django + Celery + Flower来实现耗时操作编程异步,并且能够在线实时监控。

不吹不黑,这篇文章是全网写的最详细的Celery+Django+Flower的文章。

获取整套教程源码唯一途径,关注『皮爷撸码』,回复『peekpa.com』

皮爷的每一篇文章,都配置相对应的代码。这篇文章的代码对应的Tag是“Advanced_06”。

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第1张图片

耗时操作

可能有同学会问,啥是耗时操作?这么的打个比方:

比如,我们每天访问Peekpa网站的数据中心,看到很多漂亮的小姐姐。突然有一天,皮爷给大家推出了一个『一键发送种子』功能。这个发送邮件的功能,其实对于后台来说就是一个耗时操作。

我们这里就拿Github线上的Peekpa代码给大家做一下例子。我们要实现的操作就是要把日本最近的10条地震信息发送给指定的邮箱。

那么在准备耗时操作之前,我们需要准备一下如何让Django发送邮件。

发送邮件

首先,如果要发送邮件,我们需要注册一个邮箱账号,126,163和QQ邮箱都可以,我们主要使用的是邮箱的SMTP服务。

我们这里以126邮箱为例。

首先注册一个126邮箱账户,请记住邮箱账号和密码。然后登陆到邮箱里面,我们找到设置选项:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第2张图片

看到关于POP3/SMTP/IMAP这个选项,其实我们的主要目标就是SMTP服务。所以打开这个选项,去页面选择开启SMTP服务:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第3张图片

在这里,不同的邮件系统可能开通流程不太一样,126的开通流程就是需要用手机APP扫描开通,不管怎么样,开通了SMTP服务就可以了。像上图一样,显示的是开通了服务。

接下来,我们就要确认各个邮件商的SMTP服务地址了,这里皮爷给大家稍微整理了一下,如果没有你注册的邮件的SMTP服务器地址,那就需要自己百度:

SMTP服务器 端口
smtp.126.com 465
smtp.qq.com 465/587
smtp.163.com 465/994

这样准备工作就做完了。我以126邮箱为例,到目前需要记住的有以下内容:

  • 邮箱账号;
  • 邮箱密码;
  • 邮箱的SMTP服务器地址;

接下来,我们要做的就是在Django中配置发邮件的内容了。

Django配置发邮件

Django框架默认是集成了发送邮件功能的。路径是django.core.mail,我们可以直接导入这个路径下的send_mail()方法,直接调动即可完成发送功能。

我们进入源码里面可以看一下send_mail()方法:

def send_mail(subject, message, from_email, recipient_list,
              fail_silently=False, auth_user=None, auth_password=None,
              connection=None, html_message=None):
    """
    Easy wrapper for sending a single message to a recipient list. All members
    of the recipient list will see the other recipients in the 'To' field.

    If auth_user is None, use the EMAIL_HOST_USER setting.
    If auth_password is None, use the EMAIL_HOST_PASSWORD setting.

    Note: The API for this method is frozen. New code wanting to extend the
    functionality should use the EmailMessage class directly.
    """

可以看到,这里传入的参数有一个recipient_list,当Django调用这个方法发送完邮件之后,收件人是能看到其他收件人的邮箱,相当于是一起发送的。这个方法是封装好的方法,如果要使用自定义的,这里说应该直接使用EmailMessage类就好,这个EmailMessage类的路径是django.core.mail里。

这里我们就方便讲解,直接给大家调用send_mail()方法来说。

在发送邮件之前,我们可以简单的在peekpa/settings.py里面这是这么几个参数:

EMAIL_HOST = "smtp.126.com"  # 发送邮件的smtp服务器(从QQ邮箱中取得)
EMAIL_HOST_USER = "[email protected]"  # 用于登录smtp服务器的用户名,也就是发送者的邮箱
EMAIL_HOST_PASSWORD = "xxxxxxxx"  # 授权码,和用户名user一起,用于登录smtp, 非邮箱密码
EMAIL_PORT = 465  # smtp服务器SSL端口号,默认是465
EMAIL_USE_SSL = True

这几个参数对应的意思:

  • EMAIL_HOST:这个就是之前上文提到的那个表格中的SMTP服务器地址,可以填写对应邮箱的地址;
  • EMAIL_HOST_USER:这个是刚才申请的开通SMTP服务的邮箱地址;
  • EMAIL_HOST_PASSWORD:在126这里,这个是登录密码,但是在QQ那里,在开通SMTP服务的时候,会让你再输入一个授权密码;
  • EMAIL_PORT:这个端口号一般填写SMTP服务的SSL端口号,因为非SSL服务,可能会在服务器上面跑不通,所以,加上SSL没错,值在上文提到的表格找对应的邮箱服务SSL端口号就可以;
  • EMAIL_USE_SSL:填写True,表示开启SSL服务;

当你配置好之后,我们简单的在网页上面实现一下,将每个地震信息下面都配置一个按钮,点击按钮就会发送地震的详细信息到指定的邮箱:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第4张图片

每个按钮给配置一个URL,负责点击事件并且发送邮件。这里就不具体的展开如何写一个URL的视图函数了,只是给大家简单的罗列几点内容:

url的格式为:jpearth/Send/

我们这里打算发送的邮件为HTML格式的邮件,发送Email的函数如下:

def send_jpearch_email(self, item):
    title = "这是一封来自Peekpa.com的邮件"
    bodyhtml = '' + \
               '

日本实时地震报告: ' + \ '地点:+ item['jp_url'] + '">' + item['jp_location'] + '' + \ '震级:+ item['jp_url'] + '">' + item['jp_level'] + '' + \ '

'
+ \ '

ID:' + item['jp_id'] + '

'
+ \ '

位置:+ item['jp_location_image_url'] + '"/>

'
+ \ '

时间:+ item['jp_url'] + '">' + item['jp_title'] + '

'
+ \ '

强度:+ item['jp_url'] + '">' + item['jp_max_level'] + '

'
+ \ '

点击上面的任意链接即可跳转到『日本气象厅』网站查看详情

'
+ \ '' send_mail( title, "this is message", # 如果没有HTML的内容,只是纯文字的,这里就是邮件的内容 '[email protected]', # settings.py 中设置的发件人邮箱 ['[email protected]'], # 收件人邮箱 fail_silently=False, html_message=bodyhtml # 如果是HTML格式,这里填写html格式的邮件内容 )

当发送完邮件之后,我们还会返回到JpEarth的list页面。

这里我们来直接测试一下,看看发送一个邮件需要多久的网页访问时间:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第5张图片

看到耗时大概1.4秒左右。这只是个很简单的发送邮件,就要耗时这么久。我们再到邮箱里检查一下:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第6张图片

我们的HTML邮件长这个样子,看着还可以。

这样,我们的耗时操作就产生了,发送邮件这么耗时。接下来,我们讲解如何使用Celery来让耗时操作异步处理。

Celery安装

首先通过pip安装Celery:

pip3 install celery==4.4.4

接着我们配置Celery。首先需要在Peekpa/settings.py文件同级的文件夹,创建一个celery.py文件:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第7张图片

这个文件里面如下配置:

from __future__ import absolute_import
import os
from celery import Celery


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Peekpa.settings')
app = Celery('peekpa')

app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

然后,需要在Peekpa/__init__.py文件中填入一下内容:

from __future__ import absolute_import, unicode_literals

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ['celery_app']

Celery还需要设置一个Brokers的东西,这个东西其实就起到一个队列的作用,一般Celery支持的Brokers有这么几种:

  • RabbitMQ
  • Redis
  • Amazon SQS

可以看到,这里有我们上篇文章说到的Redis!Redis!快速的Redis。

所以,我们直接拿Redis来作为我们的Borkers。但是需要设置。设置方法需要在Peekpa/settings.py文件里配置:

# CELERY
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
# CELERY_BEAT_SCHEDULE = {}

接着,我们在datacenter目录下,创建一个tasks.py文件

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第8张图片

我们把之前的发送Email的方法搬到这个文件里面,并且加一个@task()注释:

from __future__ import absolute_import, unicode_literals
from celery import task
from django.core.mail import send_mail


@task()
def send_peekpa_email(item):
    title = "这是一封来自Peekpa.com的邮件"
    bodyhtml = 'xxxxx'
    send_mail(
        title,
        "this is message",
        '[email protected]',
        ['[email protected]'],
        fail_silently=False,
        html_message=bodyhtml
    )

只有加了@task()注释的方法,才会被Celery发现,运行的时候才会被扔到Borker里面。

所以,这个时候我们修改一下之前的发送视图函数,用send_peekpa_email.delay(jp_item)替换掉之前的发送邮件方法。

注意,这里需要加delay,否则还是同步方法。

这样,我们的Celery就准备好了。

启动测试Celery

如果要Celery,需要同时启动celery beatcelery worker这两个。我们这里对应上面配置的项目,启动命令分别如下:

# 启动celery worker
$ celery worker -A Peekpa --loglevel=INFO

# 启动celery beat
$ celery beat -A Peekpa --loglevel=INFO

我们分别用两个Terminal启动这个两个命令。注意一下前提:需要提前启动好本地的Redis,需要提前启动好本地的Redis,需要提前启动好本地的Redis。启动完之后是这个样子:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第9张图片

这个时候,我们再去页面里面发送邮件,看看这回用时多少:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第10张图片

看到只用时85毫秒,而且之后邮箱里面也收到了邮件。是不是非常的爽??

至此,我们就把如何使用Celery异步的处理费事操作说完了。

当然,Celery还可以用来做定时器,就是让Django在一定规律的时间之内执行一段代码,比如每天晚上7点来执行检查任务,将今天爬虫爬下来多少数据统计一下,然后发送到自己的邮箱里。具体的做法很简单。

首先,在tasks.py文件里面,还是写好方法,用@task()来给方法加注解。

然后需要在settings.py文件里面,我们之前提到有个变量CELERY_BEAT_SCHEDULE = {}, 这里面的写法,可以参考以下:

from datetime import timedelta

CELERY_BEAT_SCHEDULE = {
    'webspider_start_jp_earch': {
        'task': 'apps.basefunction.tasks.webspider_start_hot_movie',
        'schedule': timedelta(hours=1)
    },
    'send_peekpa_email': {
        'task': 'apps.basefunction.tasks.send_peekpa_email',
        'schedule': crontab(hour="0-23/6")
    },
}

这里面,hot movie的爬虫,是每一个小时运行一次,发送邮件,则是每6个小时运行一次。启动方式还是和之前的启动一样,同时运行celery workerceler beat

Flower在线监控

既然我们的异步任务能够用Celery执行,我们可以试用Flower来实现在线监控我们的Celery任务。

首先,安装Flower:

pip3 install flower==0.9.5

然后,启动Flower之前,首先启动Redis,Celery,然后才启动Flower。

启动方法是,在项目目录下:

$ flower -A Peekpa --port=5555

中间的是项目名,和Celery中的一样,然后端口号我们随便设置,这里是5555,接着我们去浏览器里面看一下效果:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第11张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltQCFH9H-1595953995562)(https://upload-images.jianshu.io/upload_images/19310624-70bd895219607144.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

可以看到,我这里在本地是每10秒打印一句“『皮爷撸码』这个号太干了”:

可以看到上面在Flower的控制台里面,能够看到每一个Celery的执行情况。是不是非常的方便???

真的,说一句心里话,这篇文章,是真的太干了。

线上部署怎么搞

项目写到这里,越来越复杂,光启动项目,就得一句这个命令,一句那个命令,今天启动两个东西,就得要三条命令。这么多命令,部署上线了记不住咋整,别慌,这些东西,其实都可以交给supervisor来做。我们这里就将启动celery两条命令,写到peekpa_supervisor.conf文件中:

[program:ScheduleWork]
command = celery worker -A Peekpa --loglevel=INFO
directory = /home/centos/PeekpaCom
startsecs=5
stopwaitsecs = 60
autostart=true
autorestart = true

[program:ScheduleWorkBeat]
command = celery beat -A Peekpa --loglevel=INFO
directory = /home/centos/PeekpaCom
startsecs=15
stopwaitsecs = 60
autostart=true
autorestart = true

成功启动Supervisor之后,我们看到的控制界面就是这样:

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第12张图片

具体的这个配置文件怎么写的,我都在整套教程的代码里面有,获取方式见文章最后。

技术总结

最后总结一下,

在Django + Celery + Flower实现异步在线管理:

  1. Django后台的异步耗时操作,可以通过Celery做完美的处理;
  2. 安装了Celery之后,需要在Peekpa/settings.py文件同级的目录,创建celery.py文件,然后在同级的__init__.py文件中,填写一下配置信息;
  3. Celery必须要有一个Broker,这里选择使用Redis,需要在Peekpa/settings.py文件中配置相关参数;
  4. Celery的耗时操作方法,提取出来,在App里面创建一个tasks.py文件,然后将方法写进去,同时,方法需要@task()注解;
  5. 视图函数里面执行耗时方法的时候,别忘了调用delay()方法;
  6. Flower可以用来检测Celery任务。

获取整套教程源码唯一途径,关注『皮爷撸码』,回复『peekpa.com』

长按下图二维码关注,如文章对你有启发或者能够帮助到你,欢迎点赞在看转发三连走一发,这是对我原创内容输出的最大肯定。

用Django全栈开发(进阶篇)——06. Django + Celery + Flower实现在线监控后台异步耗时操作_第13张图片

你可能感兴趣的:(Peekpa.com,Django,Python,python,django,flask)