flask+celery 任务状态查看与删除
前言
写这个的原因是网上关于celery+flask
操作的很多博客大多停留在delay
添加异步任务的阶段,但是对于任务状态的查看和卡顿任务的删除进行讲解的却很少,即便有,很多也是关于django
的,对于flask
操作人员不太友好
所以在这篇博客中会以最简的方式实现这两个功能
环境
celery
,redis
,flask
,python3
操作系统 windows10
注册celery实例
def make_celery(app):
celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
TaskBase = celery.Task
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
with app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
celery.Task = ContextTask
return celery
#注册celery实例
celery = make_celery(app)
任务状态查看
celery
的broker
由redis
担任
使用state
来存储任务的状态,celery
的内置状态有:
参数 | 说明 |
---|---|
PENDING | 任务等待中 |
STARTED | 任务已开始 |
SUCCESS | 任务执行成功 |
FAILURE | 任务执行失败 |
RETRY | 任务将被重试 |
REVOKED | 任务取消 |
PROGRESS | 任务进行中 |
当然我们也可以自定义相关的状态,将状态以不同的样式显示出来
想要获取到任务执行的状态,我们需要先将celery
的任务进行绑定
任务绑定到实例获取到任务的上下文,我们就可以在任务运行时候获取到任务的状态,记录相关日志等
如何进行任务绑定,给任务添加bind=True
参数,如下
@celery.task(bind=True)
def scanIndex(self,url):
添加了bind
参数之后,函数的参数发生变化, 多出了参数 self, 这这相当于把 scanIndex
变成了一个已绑定的方法, 通过 self
可以获得任务的上下文
我们先使用delay
创建任务
tempResult=scanIndex.delay(url)
delay
会返回给我们一个AsyncResult
实例,不管什么时候,我们都可以通过返回的实例的task_id
从redis
查找执行的结果,比如你在执行一个任务,你可以设置一个周期性轮询,去查看这个结果是否已经被生产出来,如果生产出来便取到该值做相应的操作即可。
tid=tempResult.task_id
我们只需要及时将这个task_id
存储起来即可,这样方便我们后面进行任务查看
这里我使用mysql
进行任务信息的存储
task
表结构为:
class Task(db.Model):
__tablename__ = 'task'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
tid= db.Column(db.String(128), nullable=False)
state= db.Column(db.String(128), nullable=False)
date = db.Column(db.String(30), nullable=False)
其中tid
为任务task_id
,state
为任务的状态,初始化任务后状态手动设置为PENDING
temptask=Task(tid=tempResult.task_id,state='PENDING',date=str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
db.session.add(temptask)
db.session.commit()
接着在我们的程序逻辑中,每到一个状态就修改任务的状态
比如,任务开始执行之后,进入执行函数,就将任务状态修改为PROGRESS
@celery.task(bind=True)
def scanIndex(self,url):
self.update_state(state="PROGRESS")
这里的self
是因为在任务绑定后的celery
任务中,update_state
方法用于更新状态
当用户在前端进行任务状态查看的时候,就先将mysql
中的每一个tid
取出来,到redis
里面去查看任务状态,并更新到mysql
中,再将新的任务状态显示在页面上即可
前端页面的显示可以使用不同的颜色来表示不同的状态
{% if task.state=='PENDING'%}
<tr class="">
{% elif task.state=='SUCCESS'%}
<tr class="success">
{% elif task.state=='FAILURE'%}
<tr class="danger">
{% elif task.state=='PROGRESS'%}
<tr class="info">
{% endif %}
</tr>
使用css
以不同的颜色以区分,更能够快速查看出错和失效的任务
任务删除
任务删除比任务状态查看更简单,我们开始任务后先到redis
里面看看任务执行之后是什么样子的
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> keys *
1) "celery-task-meta-ac453fe5-e1c2-43b8-a923-dd4e8df9702a"
2) "_kombu.binding.celery"
127.0.0.1:6379>
而后面的ac453fe5-e1c2-43b8-a923-dd4e8df9702a
正是任务task_id
所以我们只需要进行简单的字符串拼接,可以获取到任务在redis
里面的全称了,接着在python
里面使用
taskname="celery-task-meta-"+tid
r.delete(taskname)
进行删除,r
是redis
的一个链接实例
mysql
里面的对应任务已经产生的数据也用类似的方法,通过tid
来进行查询删除即可
达到删除celery
任务的效果
参考链接
- https://www.celerycn.io/yong-hu-zhi-nan/ren-wu-tasks/zhuang-tai-states
- https://www.cnblogs.com/wdliu/p/9517535.html
- https://www.pyfdtic.com/2018/03/16/python-celery-%E4%BB%BB%E5%8A%A1%E9%98%9F%E5%88%97/
END
建了一个微信的安全交流群,欢迎添加我微信备注进群
,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 😃