celery分布式任务队列

 

1.概述:

1.celery是一个基于python开发的分布式异步消息任务队列,通过它可以轻松实现任务的异步处理。

2.celery是消费者、生产者、中间件(消息队列) 封装在一起的模块

 

2.celery流程:

 

 

3.使用场景:

  • 你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。
  • 定时任务,比如每天检测一下你们所有客户的资料,如果发现今天 是客户的生日,就给他发个短信祝福。
  • 异步发邮件 , 一般发邮件比较耗时的操作,需要及时返回给前端,这个时候 只需要提交任务给celery 就可以了.之后 由worker 进行发邮件的操作 。

 

4.安装:

4.1 linux下使用Docker安装Redis和RabbitMQ

 

#安装redis(--requirepass表示设置密码)
docker run -d --name myredis -p 6379:6379 redis --requirepass "123456aBaB"

#安装rabbitmq docker run -d --name Myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management

 

4.2 安装celery
pip install  -U celery

 

4.3 如果是windwos还需安装eventlet(linux就不用)

pip install eventlet

 

5.开始使用:

 5.1编写tasks.py

#!/usr/bin/env python
# encoding: utf-8

from celery import Celery

#________________________________________通过函数映射执行worker_test模块________________________________
##roker消息队列(可以选择Redis或者mq 更推荐mq),  backend存储任务执行结果(一般可选redis)
celery = Celery('tasks', broker="redis://:123456aBaB@106.55.29.87:6379/1",
                backend="redis://:123456aBaB@106.55.29.87:6379/2")

##name为指定任务的名字
@celery.task(name='run_job_delay')
def run_job_delay(a, b):
    print('执行异步任务')

##name为指定任务的名字
@celery.task(name='run_job_delay_1')
def run_job_delay_1(url):
    print('执行异步任务-请求url')



if __name__ == "__main__":
    #使用delay发送异步任务
    res=run_job_delay.delay('chen', 'wei20222')
    print(res.id)
    #res.wait()#等待任务完成, 返回任务执行结果,很少使用
    print(res.result)

    ##使用delay发送异步任务
    res=run_job_delay_1.delay('https://qqlykm.cn/api/api/tq.php?city=%E5%8C%97%E4%BA%AC')
    print(res.id)#获取任务id
    res.wait()#等待任务完成, 返回任务执行结果,很少使用
    print(res.result)#获取结果


###___________________________也可以直接调用worker_test模块______________________________
# from celery import Celery
# from worker_test import run_job_delay
#
# res=run_job_delay.delay('chen', 'wei20222')
# print(res.id)

 

 

 5.2编写worker_test.py代码

#!/usr/bin/env python
# encoding: utf-8
__author__ = "晨晨"

import time
import logs
import requests
from celery import Celery


#broker是mq的地址,backend是redis的
# celery = Celery('tasks', broker="amqp://admin:admin@106.55.29.87:5672/",
#                 backend="redis://:123456aBaB@106.55.29.87:6379/0")

celery = Celery('tasks', broker="redis://:123456aBaB@106.55.29.87:6379/1",
                backend="redis://:123456aBaB@106.55.29.87:6379/2")

@celery.task(name='run_job_delay')
def run_job_delay(a,b):
    time.sleep(15)
    logs.debug('99999999999999999999999999999999999999')#写入日志
    return a+b#返回执行结果给Backend


@celery.task(name='run_job_delay_1')
def run_job_delay_1(url):
'''通过celry处理url请求''' time.sleep(
30) ruset= requests.get(url) res=ruset.text return res#返回执行结果给Backend

 

 

5.3启动worker,在worker目录所在的cmd命令行下执行命令,我没写错是的在命令行下

celery worker -A worker_test -l info -P eventlet

  worker是worker.py的模块名字, -l是日志级别 -P eventlet是windows下启动报错所以加这个参数,需要自己手动安装一下eventlet

 

5.4运行task.py,发送任务到MQ,此时可以打开mq的控制台看到一条消息插入了队列。

 

5.5worker可以看到日志输出

收到了任务ID为"1bbf4e58-70ec-457c-9762-4ff0157863fd"

任务名称为"run_job_delay"的任务,worker执行任务输出了结果3。

[2022-01-06 15:37:16,205: INFO/MainProcess] Connected to redis://:**@106.55.29.87:6379/1
[2022-01-06 15:37:16,267: INFO/MainProcess] mingle: searching for neighbors
[2022-01-06 15:37:17,509: INFO/MainProcess] mingle: all alone
[2022-01-06 15:37:17,696: INFO/MainProcess] pidbox: Connected to redis://:**@106.55.29.87:6379/1.
[2022-01-06 15:37:18,920: INFO/MainProcess] celery@PC-20181101ITDM ready.
[2022-01-06 15:37:33,836: INFO/MainProcess] Received task: run_job_delay[c5e35633-0505-4b04-b3e5-2f8618979ee8]
[2022-01-06 15:38:03,855: DEBUG/MainProcess] 99999999999999999999999999999999999999
[2022-01-06 15:38:03,896: INFO/MainProcess] Task run_job_delay[c5e35633-0505-4b04-b3e5-2f8618979ee8] succeeded in 30.046000000089407s: 'chentest123'

 

5.6实际项目中使用时我会在场景执行的方法中传递场景ID等参数到worker,然后由worker进行异步执行。

 

5.7查看任务执行状态以及结果

#!/usr/bin/env python
# encoding: utf-8
from celery.result import AsyncResult
from worker_test import celery

async = AsyncResult(id="c4bf7254-5021-428a-af07-13099156d7a7", app=celery)

if async.successful():
    result = async.get()#获取结果
    print(result)
    #result.forget() # 将结果删除
elif async.failed():
    print('执行失败')
elif async.status == 'PENDING':
    print('任务等待中被执行')
elif async.status == 'RETRY':
    print('任务异常后正在重试')
elif async.status == 'STARTED':
    print('任务已经开始被执行')

 

 

 

 

日志模块:

#!/usr/bin/env python
# encoding: utf-8
__author__ = "晨晨"

import logging,time

#______________________________________________________________日志处理_____________________________________________________________________


def debug(news):
    # 创建一个logger
    logger = logging.getLogger('mylogger')
    logger.setLevel(logging.DEBUG)

    timestr = time.strftime('%Y-%m-%d__%H_%M_%S', time.localtime(time.time()))
    filename = './' + timestr + '.log'  # 日志文件的地址
    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler(filename)
    fh.setLevel(logging.DEBUG)

    # 再创建一个handler,用于输出到控制台
    #ch = logging.StreamHandler()
    #ch.setLevel(logging.DEBUG)

    # 定义handler的输出格式
    formatter = logging.Formatter('[%(asctime)s][%(thread)d][%(filename)s][line: %(lineno)d][%(levelname)s] ## %(message)s')

    fh.setFormatter(formatter)
    #ch.setFormatter(formatter)#打印到控制台

    # 给logger添加handler
    logger.addHandler(fh)
    #logger.addHandler(ch)#打印到控制台
    logger.debug(news)# 记录一条日志
View Code

 

6.一些方法:

r.ready()     # 查看任务状态,返回布尔值,  任务执行完成, 返回 True, 否则返回 False.
r.wait()      # 等待任务完成, 返回任务执行结果,很少使用;
r.get(timeout=1)       # 获取任务执行结果,可以设置等待时间
r.result      # 任务执行结果.
r.state       # PENDING, START, SUCCESS,任务当前的状态
r.status      # PENDING, START, SUCCESS,任务当前的状态
r.successful  # 任务成功返回true
r.traceback  # 如果任务抛出了一个异常,你也可以获取原始的回溯信息
r.id #获取任务id

 

 

 备注:

1.修改了worker_test消费者,需要重启worker不然不生效。

 

相关连接:

https://blog.csdn.net/u010339879/article/details/97691231 ....................celery 简要概述

https://www.cnblogs.com/huahuawang/p/14813546.html .............................celery介绍
https://mp.weixin.qq.com/s/o4vn94YS1sudY9EhDBlSCw .................................【Celery实践一】安装以及入门
https://www.cnblogs.com/zhaopanpan/p/10032853.html .................................celery基本使用
https://zhuanlan.zhihu.com/p/31731892 ......................................................Kafka是一个分布式流处理系统

posted on 2022-01-06 12:01  chen_2987  阅读(200)  评论(0)    收藏  举报

导航