Flask 与 Celery 异步任务的完美结合

Flask 与 Celery 异步任务的完美结合:一个轻松有趣的教程

为了防止在长时间不使用工具框架后遗忘其使用方法,以此记录,也希望这些记录对你有所帮助。

安装依赖

首先,咱们得安上咱们的必备工具,非常简单,打开命令行,输入:

pip install Flask Celery redis eventlet

windows10 使用celery必须 安装 eventlet

别担心,这些命令跑起来很快,就像夜店门口的小奶狗一样贴心。

模块化配置

工欲善其事,必先利其器。我们将代码分成几个模块,方便管理和阅读。

celery_config.py

这个模块用来配置 Celery。就像每个故事都需要一个好的开篇,Celery 也需要被好好配置。

# celery_config.py

from celery import Celery

def make_celery(app):
    """
    配置 Celery,与 Flask 应用绑定。
    :param app: Flask 应用实例
    :return: 配置好的 Celery 实例
    """
    # 初始化 Celery 的 broker 和 backend
    celery = Celery(
        app.import_name,
        broker=app.config['CELERY_BROKER_URL'],
        backend=app.config['CELERY_RESULT_BACKEND']
    )
    celery.conf.update(app.config)  # 更新 Celery 配置
    return celery  # 返回 Celery 实例

tasks.py

这个模块用来定义我们的任务。就像我们平时爱 procrastinate 而不做的事情一样,但 Celery 可是不会偷懒的。

# tasks.py

from celery_config import make_celery
from flask import Flask

app = Flask(__name__)
# 配置 flask 应用的 broker 和 backend 地址
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'

celery = make_celery(app)

@celery.task(bind=True)
def long_task(self):
    """
    一个模拟耗时任务的函数。例如:长时间计算、调 API 等。
    :param self: Celery 任务实例
    :return: 任务完成信息
    """
    import time
    time.sleep(10)  # 模拟长时间的任务
    return '任务完成!'

app.py

这是我们的主战场,Flask 应用的大本营。在这里,我们定义 API 路由和服务逻辑。

# app.py

from flask import Flask, request, jsonify
from tasks import long_task

app = Flask(__name__)

@app.route('/start_task', methods=['POST'])
def start_task():
    """
    启动一个异步任务。
    :return: 返回任务 ID
    """
    task = long_task.apply_async()  # 异步调用任务
    return jsonify({'task_id': task.id}), 202  # 返回任务 ID 和状态码 202

@app.route('/task_status/<task_id>', methods=['GET'])
def task_status(task_id):
    """
    查询任务状态。
    :param task_id: 任务 ID
    :return: 返回任务的当前状态和结果
    """
    task = long_task.AsyncResult(task_id)  # 获取任务结果
    if task.state == 'PENDING':
        response = {
            'state': task.state,
            'status': '等待中...'
        }
    elif task.state != 'FAILURE':
        response = {
            'state': task.state,
            'result': task.result  # 如果任务成功,返回结果
        }
        if task.state == 'PROGRESS':
            response['meta'] = task.info  # 任务进行中时的额外信息
    else:
        response = {
            'state': task.state,
            'status': str(task.info)  # 任务失败,返回错误信息
        }
    return jsonify(response)  # 返回 JSON 格式的响应

if __name__ == '__main__':
    app.run(debug=True)  # 启动 Flask 应用

配置和运行 Celery

Celery 的配置可是非常灵活的,为了让你的 Celery 跟火箭一样高效,咱们来讲几个常用的配置参数。(非必须)

celery.conf.update(
    task_serializer='json',
    accept_content=['json'],  # 这使得 Celery 只接收 JSON 格式的数据
    result_serializer='json',
    timezone='UTC',
    enable_utc=True,
)

启动 Redis 服务

先确保 Redis 在本地运行。你可以通过以下命令启动 Redis 服务器:

redis-server

启动 Celery Worker

在一个新的终端窗口中启动 Celery worker:

celery -A tasks.celery worker --loglevel=info

让 Celery worker 跑起来,准备接受任务吧!
好的,接下来我们详细讲解一下 .delay().apply_async() 的区别,以及 Celery 启动命令的参数。

Celery 启动命令参数介绍

启动 Celery worker 可以使用非常多的参数配置,除了基本的 -A--loglevel,我们来讲解一下 -P 和其他一些重要参数:

celery -A celery_app.celery worker -P eventlet --loglevel=info
  • -A celery_app.celery: 这里的 -A 表示指定 Celery 应用实例,celery_app.celery 的意思是我们在 celery_app.py 文件中定义了 celery 实例。(根据自己的文件名来)

  • -P eventlet: 这里的 -P 是指工作模式(Pool),eventlet 是一种协程库(类似于 gevent),适用于需要处理大量 I/O 操作的任务。默认的 Pool 是 prefork,适用于 CPU 密集型任务。

    • prefork: 默认进程池模式。适合 CPU 密集型任务。
    • solo: 单进程模式。适合调试和开发。
    • eventlet: 使用 Eventlet 协程。适合 I/O 密集型任务。
    • gevent: 使用 Gevent 协程。适合 I/O 密集型任务。
  • --loglevel=info: 这里是设置日志级别,常见的日志级别包括 DEBUGINFOWARNINGERRORCRITICAL。在生产环境中,一般设置成 INFO 或更高级别。

其他一些有用的 Celery 参数

  • --concurrency: 设置任务并发的 worker 数量。默认情况下,Celery 会自动设置为可用 CPU 的数量。

    celery -A celery_app.celery worker --concurrency=4
    
  • --time-limit--soft-time-limit: 设置任务执行的时间限制(硬/软时间限制)。软时间限制会给任务一个即时的取消信号,而硬时间限制会强制终止任务。

    celery -A celery_app.celery worker --time-limit=300 --soft-time-limit=200
    
  • -Q--queues: 指定 worker 监听的队列。这样可以将某些任务发送到特定的队列,从而仅让某些 worker 处理这些任务。

    celery -A celery_app.celery worker -Q high_priority,low_priority
    
  • -n--hostname: 设置 worker 的 hostname。这在部署多个 worker 时很有用,可以对它们进行区分。

    celery -A celery_app.celery worker -n worker1@%h
    

启动 Flask 应用

最后,在另一个终端中启动 Flask 应用:

python app.py

测试 API

  1. 启动一个任务:

    curl -X POST http://127.0.0.1:5000/start_task
    

    你会收到一个任务 ID,像这样:

    {"task_id": "some_task_id"}
    
  2. 查询任务状态:

    curl http://127.0.0.1:5000/task_status/some_task_id
    

瞧,这就是一个完整的流程!你现在可以优雅地处理那些耗时任务,伴随着红茶和 Python 的清香,在一切运转良好的情况下,恭喜你,你已经成功集成了 Flask 与 Celery!

如果你觉得这有意思,记得给自己点个赞!继续探索,继续编程,加油!👨‍💻👩‍💻🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值