• Python Flask后端异步处理(二)


      在实际的应用场景中,如用户注册,用户输入了注册信息后,后端保存信息到数据库中,然后跳转至登录界面,这些操作用户需要等待的时间非常短,但是如果是有耗时任务,比如对输入的网址进行漏洞扫描,在后端处理就会花费几分钟的时间,不可能让用户等待页面刷新几分钟,所以需要进行后端异步处理。之前使用的后端异步处理时Python的原生线程/进程实现,简洁暴力,自己用的话还行,但是如果是给用户用,就还存在一些不足,现考虑使用Celery替换掉原生线程/进程异步处理。

    Celery

      Celery是个Python语言实现的异步分布式任务队列服务,除了支持即时任务,还支持定时任务,Celery有五个核心角色。

    • Task 任务

      任务(Task)就是你要做的事情,例如一个注册流程里面有很多任务,给用户发验证邮件就是一个任务,这种耗时的任务就可以交给Celery去处理,还有一种任务是定时任务,比如每天定时统计网站的注册人数,这个也可以交给Celery周期性的处理。

    • Broker 经纪人,队列,消息传递者

      Broker 的中文意思是经纪人,指为市场上买卖双方提供中介服务的人。在Celery中这个角色相当于数据结构中的队列,介于生产者和消费者之间经纪人。例如一个Web系统中,生产者是主程序,它生产任务,将任务发送给 Broker,消费者是 Worker,是专门用于执行任务的后台服务。Celery本身不提供队列服务,一般用Redis或者RabbitMQ来实现队列服务。

    • Worker 执行者,消费者

      Worker 就是那个一直在后台执行任务的人,也成为任务的消费者,它会实时地监控队列中有没有任务,如果有就立即取出来执行。

    • Beat 定时任务调度器

      Beat 是一个定时任务调度器,它会根据配置定时将任务发送给 Broker,等待 Worker 来消费。

    • Backend 执行结果

      Backend 用于保存任务的执行结果,每个任务都有返回值,比如发送邮件的服务会告诉我们有没有发送成功,这个结果就是存在Backend中,当然我们并不总是要关心任务的执行结果。

    celery.png

      接下来编写一个简单的python程序来学习使用Celery

      首先是安装Celery,因为我的开发平台是Windows,Celery新版是不支持Windows操作系统的,需要下载老版本的,这里参考github上Celery开发者的回答:  https://github.com/celery/celery/issues/4178

      下载3.1.24版本的Celery

    pip3 install celery==3.1.24

      此外还要下载Reids,并且启动Redis的服务,此处百度

    创建Celery实例

    # task.py
    from celery import Celery
    ​
    app = Celery('task', broker='redis://localhost:6379/0')

    创建任务

    #task.py
    @app.task
    def send_mail(email):
        print("send mail to ", email)
        import time
        time.sleep(5)
        return "success"

      默认读者有flask基础,另外这里使用app.task 包装 send_email , 使其成为后台运行的任务

      函数使用app.task装饰器修饰之后,就会成为Celery中的一个Task。

    启动Worker

      启动Worker,监听Broker中是否有任务

    celery worker

      可以带参数如

    celery -A task worker --loglevel=info

      -A: 指定 celery 实例所在哪个模块中,--loglevel:显示日志等级

      运行后如下

    bug5.png

    调用任务

      在主程序中调用任务,调任务发送给Broker,跟开一个多线程和多进程类似,相当于是把任务丢给了Broker,主程序继续向下执行。

    from task import send_mail
    ​
    def register():
        import time
        start = time.time()
        print("1. 插入记录到数据库")
        print("2. celery 帮我发邮件")
        send_mail.delay("xx@gmail.com")
        print("3. 告诉用户注册成功")
        print("耗时:%s 秒 " % (time.time() - start))
    ​
    if __name__ == '__main__':
        register()

      因为send_mail被app.task装饰器修饰了,所以我们想要把任务丢给它,使用函数的 .delay方法即可

      目录结构为:

    ── Celery测试
       ├── task.py
       └── user.py

      运行user.py,查看运行结果为:

    bug6.png

      可知

    time.sleep(5)

      被丢到后台去执行了,所以花费时间这么短。如果按照正常的同步逻辑去实现,至少需要5秒钟的时间,因为存在time.sleep(5)来模拟发送邮件。

      在worker服务窗口查看日志信息

    bug7.png

      跟着大佬们的博客学习了Celery的基本操作,大部分时间去安装环境了,淦

      将Celery添加进碎遮项目会在下一篇博客中说到。

      请听下回分解 咕咕咕

    安装出现的错误

    File "d:python3libsite-packagesceleryconcurrencyprefork.py", line 20, in <module> from celery.concurrency.base import BasePool File "d:python3libsite-packagesceleryconcurrencyase.py", line 21, in <module> from celery.utils import timer2 File "d:python3libsite-packagesceleryutils imer2.py", line 19 from kombu.async.timer import Entry, Timer as Schedule, to_timestamp, logger ^ SyntaxError: invalid syntax

    bug1.png

      参考自:https://www.cnblogs.com/zivli/p/11517797.html

      这个是python3.7目前不支持kombu,降低python版本至3.6即可,(又得重新装一波python,没装conda呜呜呜,卸载之前先把python的类库输出到requirements.txt文件

      关于卸载python,可以参考这篇博客:https://blog.csdn.net/ke_yi_/article/details/88183474

      如果电脑上是python2和python3共存,请看:https://blog.csdn.net/autista/article/details/73650943

      弄好了之后再把之前python3.7的库文件恢复到python3.6里面来

    pip3 install -r requirements.txt

      弄好了之后重新打开python的集成开发环境

    celery -A task worker --loglevel=info

    bug2.png

      可算能运行Celery了

      接着运行程序的时候又遇到了

    AttributeError: 'str' object has no attribute 'items'

    bug3.png

      出现该问题的原因是redis版本过高,降低redis版本即可

    pip3 install redis==2.10.6

      然后就没有遇到其他的坑了,遇到再补:D

    参考链接

     

  • 相关阅读:
    重构之重新组织函数(Split Temporary Variable)
    HammperSpoon 不能 Focus Google Chrome 的问题
    如何让 vim 可以在命令行执行命令并且附加参数
    This bison version is not supported for regeneration of the Zend/PHP parsers
    php cURL library is not loaded
    aws linuxbrew GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2
    gen-cpp/.deps/ChildService.Plo: No such file or directory
    快速解码base64和utf-8的ASCII编码和URL解码
    英文版firefox显示中文字体丑的问题
    linux find 反转 查找没有被找到的结果
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/13192925.html
Copyright © 2020-2023  润新知