实现flask+celery+redis异步任务

一、概念

Celery是一个异步任务的调度工具。

在Celery中几个基本的概念,需要先了解下,不然不知道为什么要安装下面的东西。概念:Broker、Backend。


什么是broker?

broker是一个消息传输的中间件,可以理解为一个邮箱。每当应用程序调用celery的异步任务的时候,会向broker传递消息,而后celery的worker将会取到消息,进行对于的程序执行。好吧,这个邮箱可以看成是一个消息队列。其中Broker的中文意思是 经纪人 ,其实就是一开始说的 消息队列 ,用来发送和接受消息。这个Broker有几个方案可供选择:RabbitMQ (消息队列),Redis(缓存数据库),数据库(不推荐),等等


什么是backend?

通常程序发送的消息,发完就完了,可能都不知道对方时候接受了。为此,celery实现了一个backend,用于存储这些消息以及celery执行的一些消息和结果。Backend是在Celery的配置中的一个配置项 CELERY_RESULT_BACKEND ,作用是保存结果和状态,如果你需要跟踪任务的状态,那么需要设置这一项,可以是Database backend,也可以是Cache backend。


对于 brokers,官方推荐是 rabbitmq 和 redis,至于 backend,就是数据库。为了简单可以都使用 redis。

来一张图,这是在网上最多的一张Celery的图了,确实描述的非常好

图片

我自己演示的是使用redis作为Broker和backend。

二、环境

首先就是准备flask、celery、redis的环境

1.flask跟celery的环境直接 pip install 就好。

2.redis的环境配置,之前已写过,是阿里云服务器上的,当然也可以使用本地环境。链接如下:

https://blog.csdn.net/weixin_44204361/article/details/108456021

三、代码

注:一下代码都是在一个test3.py文件里的。并且是按照顺序一步一步往下贴的。具体文件目录如下:

图片

其他的文件时没有用到的,只用到了test3.py跟上级目录testPython

1.首先导入必要的包
from flask import Flask
from celery import Celery
import time
2.配置flask以及celery

redis://127.0.0.1:6379/0,这里的0对应的就是db0,1就是db1,以此类推。
图片

app = Flask(__name__)
# 用以储存消息队列,db0作为broker
app.config['CELERY_BROKER_URL'] = 'redis://127.0.0.1:6379/0'
# 用以储存处理结果,db1作为backend,这里随意选择db,也都可以是0或者其他。
app.config['CELERY_RESULT_BACKEND'] = 'redis://127.0.0.1:6379/1'celery_ = Celery('testPython', broker=app.config['CELERY_BROKER_URL'],include=['testPython'],backend=app.config['CELERY_RESULT_BACKEND'])
celery_.conf.update(app.config)
3.定义一个路由用来请求

@app.route("/sum/<arg1>/<arg2>")
def sum_(arg1, arg2):
# 发送任务到celery,并返回任务ID,后续可以根据此任务ID获取任务结果
result = my_background_task.delay(int(arg1), int(arg2))
return result.id

4.定义my_backgroud_task任务

##my_background_task就是需要定义的任务名
@celery_.task()
def my_background_task(arg1, arg2):
    # 两数相加,sleep 5s
    time.sleep(5)
    return arg1 + arg2

5.定义根据task_id获取结果的路由

@app.route("/getResult",methods=['post','get'])
def get_result():
    # 根据任务ID获取任务结果
    id = flask.request.values.get('id')
    ##如果不加celery_,会报错
    result = celery_.AsyncResult(id=id)
    print('result----------------')
    print(result)
    return str(result.get())

6.最后加上启动函数

if __name__ == '__main__':
    app.run(debug=True)

四、测试

1.首先启动flask服务

图片

2.启动celery

我个人觉得,celery的启动是挺坑的。首先就是celery的启动命令。

运行方式:点击Terminal,进入项目的根目录,也就是 E:\gdkyPythonCode。

(1)第一种情况:

之前的代码:为'testPython'也就是test3.py的上一级目录名。include=[testPython]
celery_ = Celery('testPython', broker=app.config['CELERY_BROKER_URL'],include=['testPython'],backend=app.config['CELERY_RESULT_BACKEND'])

然后在Terminal中运行:

celery -A testPython worker -l info 

结果:
图片

这里是celery并没有加载到到celery应用,第一感觉还是启动路径有问题。

(2)第二种情况:

celery_ = Celery('testPython.test3', broker=app.config['CELERY_BROKER_URL'],include=['testPython.test3'],backend=app.config['CELERY_RESULT_BACKEND'])

然后在Terminal中运行:

celery -A testPython.test3  worker -l info

结果:
图片

依然是报错,但又出现了了flask对象没有属性user_options 醉了 。。。o(╥﹏╥)o

(3)第三种情况:

这个celery_不改变,与第二种情况一样。

celery_ = Celery('testPython.test3', broker=app.config['CELERY_BROKER_URL'],include=['testPython.test3'],backend=app.config['CELERY_RESULT_BACKEND'])

然后在Terminal中运行:

celery -A testPython.test3.celery_  worker -l info

就是在testPython.test3后加上test3.py文件中定义的celery_
结果:

图片

好像是运行成功了!!接下来测试亿下。

回到flask路由这里,postman访问下sum接口:

图片

可以看到,确实是一旦请求,就立马返回了任务id。因为sum接口中的my_background_task方法是有5s等待的。这时候去看下redis。

图片

tips:redis中也确实是db0作为broker,db1作为结果存储。

找到刚才postman返回的那个id对应的key,可以看到value中的status为"FAILURE",说明虽然返回了任务id,但是并没有成功。回头看下后端报错情况。

图片

经过百度,大多数都是说需要安装一个扩展eventlet,接下来第四种情况。

(4)第四种情况

首先安装扩展eventlet

pip install eventlet 

这个celery_不改变,与第二种,第三种情况一样。
重启flask服务,然后在Terminal中运行:

celery -A testPython.test3.celery_  worker -l info -P eventlet

结果:
图片

接下来测试一哈,访问sum接口:

图片

然后看下后端以及redis

图片

这里的succeeded in 5.0s就是任务运行时间,后面的20则是返回的结果。

图片

看到这,感觉好多了。()

然后去请求下getResult接口,肯定也是成功滴!!

图片

五、部署

postman请求服务器上一个耗时接口:

图片

图片

图片

图片

运行的过程跟本地基本一样,只不过需要把broker跟backend的地址改下:

# 用以储存消息队列
server.config['CELERY_BROKER_URL'] = 'redis://:root@X.X.X.X:6379/0'
# 用以储存处理结果
server.config['CELERY_RESULT_BACKEND'] = 'redis://:root@X.X.X.X:6379/1'

需要加上服务器上的redis密码,我的密码是root,所以在地址前面加上root
至此flask+celery+redis的运用算是结束了,过程艰辛,方法就是不断的百度和尝试。有不对的地方或疑问可以评论留言,看到会第一时间回复滴。

图片

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薄衫啊

三克油

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值