flask+celery 任务状态查看与删除

前言

写这个的原因是网上关于celery+flask操作的很多博客大多停留在delay添加异步任务的阶段,但是对于任务状态的查看和卡顿任务的删除进行讲解的却很少,即便有,很多也是关于django的,对于flask操作人员不太友好

所以在这篇博客中会以最简的方式实现这两个功能

环境

celeryredisflaskpython3

操作系统 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)

任务状态查看

celerybrokerredis担任

使用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_idredis查找执行的结果,比如你在执行一个任务,你可以设置一个周期性轮询,去查看这个结果是否已经被生产出来,如果生产出来便取到该值做相应的操作即可。

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_idstate为任务的状态,初始化任务后状态手动设置为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以不同的颜色以区分,更能够快速查看出错和失效的任务

img

任务删除

任务删除比任务状态查看更简单,我们开始任务后先到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)

进行删除,rredis的一个链接实例

mysql里面的对应任务已经产生的数据也用类似的方法,通过tid来进行查询删除即可

达到删除celery任务的效果

参考链接

END

建了一个微信的安全交流群,欢迎添加我微信备注进群,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 😃

GIF GIF
posted @ 2021-09-23 00:39  春告鳥  阅读(3246)  评论(1编辑  收藏  举报