python使用celery实现异步任务

目录

一、使用celery

二、通用celery项目目录结构

三、相关文件代码

3.1、celery启动文件

3.2、celery配置文件

3.3、异步任务定义

3.4、异步任务调用

四、celery启动命令

五、其他


一、使用celery

celery需要中间件来做消息传递和结果存储,常用的消息中间件为:RabbitMQ、RocketMQ、Redis,其中redis最为方便,但没有web管理页面。

python 复制代码
pip install celery
pip install redis  # 使用 Redis 作为 broker/backend

二、通用celery项目目录结构

复制代码
project/                        # 项目root根路径
├── celery_app/                 # celery根目录
│   ├── tasks/                  # celery taks异步任务分模块
│   │   ├── module1/
│   │   │   ├── __init__.py
│   │   │   └── tasks.py
│   │   ├── module3/
│   │   │   ├── __init__.py
│   │   │   └── tasks.py
│   │   ├── module3/
│   │   │   ├── __init__.py
│   │   │   └── tasks.py
│   │   ├── __init__.py
│   ├── __init__.py             # celery启动文件(也可以写一个其他的py文件作为入口)
│   └── config.py               # celery配置文件

三、相关文件代码

3.1、celery启动文件

python 复制代码
# __init__.py
from celery import Celery
from celery_app.config import broker_url, result_backend

# 创建 Celery 实例
app = Celery(
    'myapp',
    broker=broker_url if broker_url else 'redis://localhost:6379/0',      # 消息代理
    backend=result_backend if result_backend else 'redis://localhost:6379/1',     # 结果后端
)

# 从配置文件加载配置(推荐)
app.config_from_object('config')

# 自动发现任务模块
app.autodiscover_tasks(['tasks'])

3.2、celery配置文件

python 复制代码
# config.py
from celery.schedules import crontab
    

# Broker 配置(使用redis的两个库作为celery的broker和backend)
broker_url = 'redis://localhost:6379/0'
result_backend = 'redis://localhost:6379/1'

# 序列化配置
task_serializer = 'json'
result_serializer = 'json'
accept_content = ['json']
timezone = 'Asia/Shanghai'
enable_utc = True

# 任务配置
task_track_started = True          # 跟踪任务开始状态
task_time_limit = 30 * 60          # 任务执行超时时间(秒)
broker_connection_retry_on_startup = True    # broker连接失败自动重试

# 结果配置
result_expires = 3600              # 结果过期时间(秒)
result_extended = True             # 存储更多结果信息

# 重试配置
task_acks_late = True              # 延迟确认任务
task_reject_on_worker_lost = True  # Worker 丢失时拒绝任务

# 并发配置(启动时也可指定)
worker_concurrency = 4             # Worker 并发数

# celery beat定时调度配置(需要启动celery_beat)
beat_schedule = {
    "test_beat_schedule": {
        "task": "celery_app.tasks.module1.tasks.celery_beat_schedule",
        "schedule": crontab(hour='10,11', minute=30),
    }
}

3.3、异步任务定义

python 复制代码
# module1.task.py
import requests

# 带重试配置的任务
@app.task(max_retries=5, default_retry_delay=60)
def request_api(url):
    try:
        response = requests.get(url, timeout=10)
        return response.json()
    except Exception as e:
        raise request_api.retry(exc=e)


# 普通异步任务
@app.task
def async_task():
    pass


# beat定时调度任务
@app.task()
def celery_beat_schedule():
    pass

3.4、异步任务调用

任务调用方面,celery提供了很多种调用方式(delay、apply_async、signature),用来处理简单的异步任务或任务链任务(B依赖A的结果这种),普遍的单个异步任务使用apply_async方法足够了。

python 复制代码
from celery_app import app
import time

# 执行异步任务获取结果

@app.task
def add(x, y):
    print(f"add 开始执行,线程: {time.strftime('%H:%M:%S')}")
    time.sleep(3)  # 模拟耗时操作
    result = x + y
    print(f"add 完成: {result}")
    return result

@app.task
def callback(result):
    print(f"callback 开始执行,线程: {time.strftime('%H:%M:%S')}")
    time.sleep(2)
    print(f"callback 完成,处理结果: {result}")
    return f"processed_{result}"

@app.task
def callback():
    print('callback回调函数执行出错时调用,若异常被捕获则不会走到这里')


if __name__ == '__main__':
    # 提交任务(带回调)
    async_result = add.apply_async(
        args=[4, 6], 
        link=callback.s(),
        link_error=callback_error.s()
    )
    async_task_id = async_result.id
    print(f"任务已提交,任务ID: {async_task_id }")
    print(f"主线程继续执行: {time.strftime('%H:%M:%S')}")

    # 使用 get()(阻塞主线程)
    result = add.delay(4, 6)
    value = result.get()  # ❌ 阻塞,等待 add 完成
    print("等待后才执行")  # 需要等待

四、celery启动命令

python 复制代码
# celery启动worker               并发数                队列                        日志级别                      后台运行      
celery -A celery_app worker --concurrency=4 --queues=high_priority,default --loglevel=info --detach --logfile=/var/log/celery.log

# celery beat调度启动
celery -A celery_app beat --loglevel=info

# 安全的停止celery
celery -A celery_app control shutdown


# 查看活跃任务
celery -A celery_app inspect active

# 查看注册的任务
celery -A celery_app inspect registered

# 查看 Worker 统计信息
celery -A celery_app inspect stats

# 查看队列长度
celery -A celery_app inspect active_queues

# 撤销任务
celery -A celery_app control revoke <task_id>

# 终止任务(强制)
celery -A celery_app control revoke <task_id> --terminate

五、其他

python 复制代码
# 常用命令
celery -A app worker -l info          # 启动 Worker
celery -A app beat -l info            # 启动 Beat
celery -A app flower                  # 启动监控
celery -A app purge                   # 清空所有消息
celery -A app inspect active          # 查看活跃任务
celery -A app control revoke <id>     # 撤销任务

# 常用装饰器
@app.task                              # 基础任务
@app.task(bind=True)                   # 绑定任务
@app.task(max_retries=3)               # 带重试
@app.task(rate_limit='10/m')           # 限流(每分钟10次)
@app.task(time_limit=30)               # 超时控制

# 常用调用
task.delay(*args, **kwargs)            # 简单调用
task.apply_async(args, countdown=10)   # 延迟调用
task.s(*args, **kwargs)                # 签名
相关推荐
iAm_Ike2 小时前
如何用 IndexedDB 存储从 API 获取的超大列表并实现二级索引
jvm·数据库·python
Land03292 小时前
指纹浏览器自动化集成方案|多浏览器RPA适配实战记录
运维·人工智能·爬虫·python·selenium·自动化·rpa
江湖中的阿龙2 小时前
消息队列核心面试题详解|RocketMQ深度剖析,含选型、可靠性、顺序性、幂等、积压、高可用、事务消息
rocketmq
X56612 小时前
CSS Flex布局如何让特定子元素不参与缩放_设置flex-shrink- 0的实战技巧
jvm·数据库·python
databook2 小时前
告别手动计算,SymPy 初识与 Manim 联动
python·数学·动效
jayson.h2 小时前
可视化界面
开发语言·python
weixin_444012932 小时前
CSS如何快速实现网站换肤功能_利用CSS变量重置全局颜色方案
jvm·数据库·python
kgduu2 小时前
python中的魔法方法
开发语言·python
m0_596749092 小时前
Vue.js计算属性computed依赖追踪与副作用函数effect关联机制
jvm·数据库·python