Celery - Task 根据任务状态执行不同的操做,和重试操作的模拟实验

背景

实验背景,拥有一堆任务需要分组分发执行。但是,糟糕的情况是每个任务的执行,大概率都是失败的。那么,如果对失败任务进行数次重试,以及如何对保存失败和成功的异步任务信息。是需要搞定的问题。

实验要求:模拟子任务的数次失败。一堆任务按照分组进行执行,且每个分组之间需要顺次执行,不可以混乱执行。并且,保证每个失败任务拥有三次的重试操作。

实验

服务端源码:

# -*- utf-8 -*-
from __future__ import absolute_import, unicode_literals, print_function
from .config import app

import os
import time
import random
import fcntl
import json
from datetime import datetime, timedelta

from celery.utils.log import get_task_logger
from celery import Task, group

logger = get_task_logger(__name__)

def func(x):
    if x in [1, 2, 3, 4]:
        raise

def write_file(x):
    date = datetime.now()
    date = '%04d%02d%02d' % (date.year, date.month, date.day)
    filename = os.path.join('./', 'test_log_%s.log' % date)

    with open(filename, 'a') as fh:
        fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
        fh.write(json.dumps(x, ensure_ascii = False) + '\n')

# 继承Task类,重写on_success, on_failure, on_retry方法
class MyTask(Task):
    def on_success(self, retval, task_id, *args, **kwargs):
        _info = 'save %s success' % args[0]
        print(_info)
        write_file(_info)

    def on_failure(self, exc, task_id, *args, **kwargs):
        _info = 'save %s failed, roll back' % args[0]
        print(_info)
        write_file(_info)

    def on_retry(self, exc, task_id, *args, **kwargs):
        _info = 'retry %s' % args[0]
        print(_info)

# 绑定任务上下文,并定义基类
@app.task(bind = True, base = MyTask)
def save(self, s):
    #logger.info(self.request.__dict__)
    try:
    	# 模拟任务的大概率异常报错
        x = random.randint(1, 5)
        func(x)
    except Exception as e:
    	# 添加任务的失败重试
        raise self.retry(exc = e, countdown = 1, max_retries = 3)

@app.task()
def distribution(indexs):
    for i in range(0, len(indexs), 5):
        start = i
        end = (i + 5) if (i + 5) <= len(indexs) else len(indexs)

        L = []
        for j in range(start, end):
            L.append(save.s(indexs[j]))

        res = group(L)()

        while not res.ready():
            time.sleep(1)

客户端源码:

from proj.tasks_1 import distribution
from celery import group

import time
from threading import Thread

def async(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target = f, args = args, kwargs = kwargs)
        thr.start()
    return wrapper

@async
def func(indexs):
   res = distribution(indexs)

def middle_func(indexs):
   func(indexs)
   return 'hello world'

if __name__ == '__main__':
   indexs = [1, 2, 3, 4, 5, 6, 7, 8]
   res = middle_func(indexs)
   print(res)

实验结果:

cat test_log_20200715.log
"save [1] success"
"save [3] success"
"save [2] failed, roll back"
"save [4] failed, roll back"
"save [5] failed, roll back"
"save [6] success"
"save [7] success"
"save [8] success"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、Celery一个分布式任务队列/消息传递系统,可以用于异步任务处理、定时任务调度等。它具有以下功能: - 异步任务处理:Celery 可以将耗时的任务放入队列,让其他进程或机器异步执行,提高系统的并发性能。 - 周期性任务调度:Celery 可以设定定时任务,按照设定的时间间隔或时间点执行任务。 - 超时任务处理:Celery 可以监控任务执行时间,并在超过设定的超时时间后自动终止任务。 - 错误重试:如果任务执行失败,Celery 可以自动重试,提高任务的可靠性。 - 任务结果存储:Celery 可以将任务执行结果存储在后端存储中,供后续查询使用。 2、Celery 可以通过创建多个队列,并使用不同的路由规则来实现不同队列执行不同任务。具体步骤如下: - 配置 Broker:在 Celery 的配置文件中,配置多个 Broker(例如 RabbitMQ 或 Redis),每个 Broker 对应一个队列。 - 定义任务:使用 Celery 的 `@task` 装饰器定义多个任务函数,并为每个任务函数指定队列的名称。 - 配置路由规则:在 Celery 的配置文件中,配置多个路由规则,将不同队列的任务关联到相应的 Broker。 - 启动 Worker:启动多个 Celery Worker 进程,每个进程连接到相应的 Broker。 - 提交任务:通过调用任务函数,并指定队列的名称,将任务提交到相应的队列。 这样,不同队列中的任务将被分发到不同的 Worker 进程执行

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值