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)# 记录一条日志
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 简要概述
浙公网安备 33010602011771号