flask+celery+redis的使用

大家好哦,最近做项目的时候,需要用到celery,这篇文章就讲一讲在flask中怎么使用celery和redis。

在开始之前,先来了解一下celery都可以做些什么

首先,它是做异步任务,例如发送邮件,短信,还可以做定时任务,还有如果接口运行时间过长的话,在不影响结果的情况下,可以先将结果返回,在用celery做异步处理。

接下来,了解一下celery的核心模块

Task:就是任务,有异步任务和定时任务

Broker:中间人,接收生产者发来的消息即Task,将任务存入队列。任务的消费者是Worker。Celery本身不提供队列服务,推荐用Redis或RabbitMQ实现队列服务。

Worker:执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它。

Beat:定时任务调度器,根据配置定时将任务发送给Broker。

Backend:用于存储任务的执行结果

了解之后,咱们开始正文

首先安装依赖celery和redis

pip install celery
pip install redis

安装redis服务

下载路径为 https://github.com/MSOpenTech/redis/releases

此刻验证一下,是否安装成功,redis-cli

安装成功之后,接下来要写代码

代码目录结构 :

celery_tasks模块主要是celery的一些配置,直接上代码

celery.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from celery import Celery

celery_app = Celery('tasks')
celery_app.config_from_object('celery_tasks.celeryconfig')
celeryconfig.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from datetime import timedelta

# celery配置

# 消息代理
BROKER_URL = 'redis://127.0.0.1:6379/0'
# 存储任务执行结果
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'
# 任务的序列化方式
CELERY_TASK_SERIALIZER = 'json'
# 任务执行结果的序列化方式
CELERY_RESULT_SERIALIZER = 'json'
# 任务过期时间
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
# 接受内容类型
CELERY_ACCEPT_CONTENT = ['json']
# 超时再分配时间
BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 3600}
# 每个worker执行了多少任务就会死掉,避免内存泄露
CELERYD_MAX_TASKS_PER_CHILD = 500
# 时区设置,用于定时任务
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = False
# 任务导入,包括异步任务和定时任务
CELERY_IMPORTS = (
    'run_server',
)
# 计划任务
CELERYBEAT_SCHEDULE = {
    'test_reminders': {
        # task就是需要执行计划任务的函数
        'task': 'run_server.test',
        # 配置计划任务的执行时间,这里是每60秒执行一次
        'schedule': timedelta(seconds=60),
        # 传入给计划任务函数的参数
        'args': None
    },
}

redis的配置

#!/usr/bin/env python
import time

import redis
from redis.exceptions import ConnectionError as RedisConnectionError


class VodRedis(redis.Redis):
    reconnect_timer = 10  # second
    connection_down_timestamp = 0

    def execute_command(self, *args, **options):
        try:
            ok_time = time.time() - (self.connection_down_timestamp + self.reconnect_timer)
            if ok_time > 0:
                self.connection_down_timestamp = 0
                return super(VodRedis, self).execute_command(*args, **options)
            return None
        except RedisConnectionError:
            self.connection_down_timestamp = time.time()
            return None

def redis_pool(db):
    return redis.ConnectionPool(host='127.0.0.1', port='6379', db=db, socket_timeout=5)


default_pool = redis_pool(0)
redis_session = VodRedis(connection_pool=default_pool)


def create_redis_session():
    return redis_session

run_server.py

#coding:utf-8
#run_server.py
import time

from flask import Flask, request, render_template
from werkzeug.utils import secure_filename
from celery_tasks.celery import celery_app
from celery.app.control import Control


#服务命名为app
from redis_tasks.redis_util import redis_session

app = Flask(__name__)


@app.route('/upload', endpoint='upload')
#此处需加endpoint,否则报错
def upload_file():
    return render_template('upload.html')


@app.route('/uploader', endpoint='uploader',methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['file']
        f.save(secure_filename(f.filename))
    for i in range(10):
        test.delay()
    return 'file uploaded successfully'


@celery_app.task(name='run_server.test')
def test():
    print('开始')
    time.sleep(10000)
    time.sleep(10000)
    print('777777')
    print('hahahha')


@app.route('/del_tasks', methods=['GET'])
def upload_file():
    if request.method == 'GET':
        task_id = request.args.get('task_id')
        # 删除redis中的key
        all_key = redis_session.keys('celery')
        if all_key:
            redis_session.ltrim('celery', 1, 0)
        # 删除celery正在执行的任务
        celery_control = Control(app=celery_app)
        celery_control.revoke(task_id, terminate=True)
        return '请求成功'
    else:
        return '请求方式不对'


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

接下来咱们要启动celery

celery -A celery_works.celery worker 

此时可能会报错

ValueError: not enough values to unpack (expected 3, got 0)

解决方法

pip install eventlet

运行命令:celery -A celery_works.celery worker -P eventlet

接下来运行项目成功后,请求接口/uploader,可以查看到redis中的任务和celery正在执行的任务,如果想要清空缓存或者是删除celery,调用接口/del_tasks

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值