python ray定时任务_Flask+Celery实现动态添加定时任务

写在前面

通过flask的web接口请求去下发celery定时任务,例如偶尔需要定期后台执行的任务,也可以在配置文件中写死相关的配置任务,例如定期刷新等操作

启动命令

celery -A application.celery worker -l INFO

存储建议

前台手动ctrl+c或者supervisor用信号kill掉celery服务会导致重启服务后任务丢失,原因是用Redis,Celery会把发送的任务临时存储在内存中,如果我们用ctrl+c或者supervisor的kill信号干掉它,那么Celery会无法将内存中的任务信息存储到Redis中.

建议使用RabbitMQ作为消息中间件,这样会实时保存任务信息

常见问题

解决Unable to load celery application.The module bin was not found.

检查celery目录问题,一般pycharm会以项目文件夹为根目录,application.celery需要写为绝对路径

解决not enough values to unpack (expected 3, got 0)问题

--pool=solo 单进程

windows下4.X版本需要指定单进程,目前不支持多进程

linux支持多进程

-P eventlet -c 1000

windows下支持eventlet线程池

Celery指定定时任务

Celery定时任务需要开启轮循,代表注册任务,读取定时任务的执行周期以及配置参数

celery -A bin.celery beat

Celery开启Worker,上面相当于流水线,这里就是工人,流水线开启后,需要开启工人(worker)去执行任务

celery -A application.celery worker -l INFO

目录结构总结

bin-

app-

flask路由文件夹

__init__.py

route.py

setting-

celery配置文件夹

__init__.py

config.py (celery基本配置)

MakeCelery.py (celery初始化类)

tasks-

异步任务目录

__init__.py

tasks.py (flask调用celery异步任务)

__init__.py (重要:初始化flask并读取config.py,通过MakeCelery.py加载celery需要的配置)

celeryWorker.py (celery服务主服务,用于单独加载配置并启动celery服务)

主要代码

routeFunc.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time : 2020/8/24 13:58

# @Author : YanMingHao

# @Site :

# @File : routeFunc.py

# @Software: PyCharm

# @notice : 我写这段代码时,知道我在做什么的,只有老天和我.但是现在,只有老天知道我在做什么.

from bin import app,jsonify,request

from bin.tasks.tasks import add_together

@app.route('/test1/',methods=['POST','GET'])

def TestRequest():

"""

测试请求

:return:

"""

data = request.get_json()

print(data)

num1 = data.get('num1')

num2 = data.get('num2')

print(num1,num2)

add_together.delay(int(num1),int(num2))

return jsonify({'count': '任务下发成功'})

if __name__ == '__main__':

app.debug = True

app.run(host='0.0.0.0',port=8888)

config.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time : 2020/8/15 10:00

# @Author : YanMingHao

# @Site :

# @File : config.py

# @Software: PyCharm

# @notice : 我写这段代码时,知道我在做什么的,只有老天和我.但是现在,只有老天知道我在做什么.

CELERY_BROKER_URL = 'redis://localhost:6379/0'

CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'

CELERY_IMPORTS = "bin.tasks.tasks" # 注册任务

CELERY_TASK_SERIALIZER = "msgpack"

CELERY_RESULT_SERIALIZER = "json"

CELERY_TASK_RESULT_EXPIRES = None

CELERY_ACCEPT_CONTENT = ['json', 'msgpack']

timezone = 'Asia/Shanghai'

enable_utc = True

MakeCelery.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time : 2020/8/15 10:03

# @Author : YanMingHao

# @Site :

# @File : MakeCelery.py

# @Software: PyCharm

# @notice : 我写这段代码时,知道我在做什么的,只有老天和我.但是现在,只有老天知道我在做什么.

from celery import Celery

def makeCelery(app):

"""

* 实例化celery

:param app:

:return:

"""

celery = Celery(

app.import_name,

backend=app.config['CELERY_RESULT_BACKEND'],

broker=app.config['CELERY_BROKER_URL']

)

celery.config_from_object(app.config)

class ContextTask(celery.Task):

def __call__(self, *args, **kwargs):

"""

* 将类变为可调用对象

:param args:

:param kwargs:

:return:

"""

with app.app_context():

"""

打开上下文

"""

return self.run(*args, **kwargs)

celery.Task = ContextTask

return celery

tasks.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time : 2020/8/24 13:58

# @Author : YanMingHao

# @Site :

# @File : tasks.py

# @Software: PyCharm

# @notice : 我写这段代码时,知道我在做什么的,只有老天和我.但是现在,只有老天知道我在做什么.

from bin import celery

import logging

from src.universal.log import record, logFile

@celery.task

def add_together(a, b):

LOGGER = record(filename=logFile('add_together.py'), level=logging.INFO)

count = a + b

LOGGER.info(f"后台任务结果为:{count}")

# return a + b

celeryWorker.py

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @Time : 2020/8/15 10:35

# @Author : YanMingHao

# @Site :

# @File : celeryWorker.py

# @Software: PyCharm

# @notice : 我写这段代码时,知道我在做什么的,只有老天和我.但是现在,只有老天知道我在做什么.

from bin import celery

if __name__ == '__main__':

# 什么都不用写,只是为了单独指定这个文件运行celery

pass

(重要)init.py

# -*- coding: utf-8 -*-

# @Time : 2020/8/17 15:13

# @Author : YinBaidong

# @function:

# @motto : Only Me and God know what it's doing!

from flask import Flask,request,jsonify

from bin.setting.MakeCelery import makeCelery

from bin.setting.path import pathFile

from bin.setting import config

app = Flask(__name__) #初始化flask

app.config.from_object(config) # 读取配置文件

celery = makeCelery(app) # 用makeCelery继承flask读取的配置

原文链接:https://blog.csdn.net/yanminghaop/article/details/108258003

你可能感兴趣的:(python,ray定时任务)