Celery 介绍
celery的使用
from flask import Flask
from celery import Celery
app = Flask(__name__)
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
正如你所见,Celery 通过创建一个 Celery 类对象来初始化,传入应用名称以及消息代理的连接 URL,这个 URL 我把它放在 app.config 中的 CELERY_BROKER_URL 的键值。URL 告诉 Celery 代理服务在哪里运行。如果你运行的不是 Redis,或者代理服务运行在一个不同的机器上,相应地你需要改变 URL。
Celery 其它任何配置可以直接用 celery.conf.update() 通过 Flask 的配置直接传递。CELERY_RESULT_BACKEND 选项只有在你必须要 Celery 任务的存储状态和运行结果的时候才是必须的。展示的第一个示例是不需要这个功能的,但是第二个示例是需要的,因此最好从一开始就配置好。
任何你需要作为后台任务的函数需要用 celery.task 装饰器装饰。例如:
@celery.task
def my_background_task(arg1, arg2):
# some long running task here
time.sleep(10)
return result
接着 Flask 应用能够请求这个后台任务的执行,像这样:
task = my_background_task.delay(10, 20)
delay() 方法是强大的 apply_async() 调用的快捷方式。这样相当于使用 apply_async():
task = my_background_task.apply_async(args=[10, 20])
当使用 apply_async(),你可以给 Celery 后台任务如何执行的更详细的说明。一个有用的选项就是要求任务在未来的某一时刻执行。例如,这个调用将安排任务运行在大约一分钟后:
task = my_background_task.apply_async(args=[10, 20], countdown=60)
delay() 和 apply_async() 的返回值是一个表示任务的对象,这个对象可以用于获取任务状态。我将会在本文的后面展示如何获取任务状态等信息,但现在让我们保持简单些,不用担心任务的执行结果。
更多可用的选项请参阅 Celery 文档 。
flask 工厂模式使用celery
在init中初始化celery实例:
#-*-coding:utf-8-*-
from celery import Celery
celery = Celery(__name__, broker='redis://127.0.0.1:6379/0',backend='redis://127.0.0.1:6379/0')
下面我们为 Celery 创建了一个工厂函数,在工厂函数中加载配置,并实现 Flask 程序上下文支持:
from flask import Flask
from flaskdemo.celery_task import celery
def make_celery(app):
celery.conf.update(app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
在使用工厂函数的 Flask 程序中初始化 Celery
当 Flask 程序也使用工厂函数创建时,我们可以全局创建 Celery 程序实例,然后在创建 Flask 程序实例的工厂函数里更新 Celery 程序配置并进行上下文设置:
def create_app(config_name=None):
if config_name is None:
config_name = os.getenv('FLASK_CONFIG', 'development')
app = Flask('flaskdemo')
app.config.from_object(config[config_name])
...
make_celery(app)
return app
在定义 Celery 任务的模块里tasks.py:
# -*- coding: utf-8 -*-
import time
from celery import current_app as celery
def send_mail():
time.sleep(20)
print('邮件发送成功')
def send_sms():
time.sleep(20)
print('短信发送成功')
@celery.task
def send_new_sms():
print('celery发送短信')
send_sms()
@celery.task
def send_new_email():
print('celery发送邮件')
send_mail()
下来启动flask程序,启动celery,需要注意的是,celery在win环境中可以接受到任务,也有提示信息,但是任务没有执行,解决办法,启动的时候,使用eventlet 方式
celery -A flaskdemo.celery worker --loglevel=info -P eventlet -c 10
-c是协程的数量,生产环境可以用1000
原因:celery不支持在windows下运行任务,需要借助eventlet来完成。