记一次celery使用过程中丢失上下文问题

问题场景

项目中需要在celery的异步任务中连接其他服务的celery任务队列,并向所连接的celery中发送task任务。 这样使用的结果就是:需要生成两个不同的celery实例,在第一个celery实例中需要使用flask中的上下文,并进行上下文的生成,在调用完另一个celery实例后, 在worker运行了标记的task最大任务销毁重启之后;会发生在需要上下文的celery异步任务中报没有flask上下文的错误。例如如下逻辑

from project import create_app()     #  封装的flask的创建app过程
from celery import Celery
from project.task import celery_config


celery_app = Celery(__name__, broker=celery_config.CELERY_BROKER_URL)   # 程序中默认celery_app
celery_app.config_from_object('project.task.celery_config')

@celery_app.task(name='example_task')
def example_task(**kwargs):
    from project import create_app
    app = create_app()
    app.app_context().push()

    # 执行默认celery异步任务

		# 执行完成后进行向其他服务发送celery task
    send_celery_task(**kwargs)

def send_celery_task(**kwargs):
    # 产生问题的位置
    push_celery_app = Celery(__name__, broker=os.environ.get("PUSH_CELERY_BROKER_URL"))
		
	push_celery_app.send_task(name=os.environ.get("PUSH_TASK_NAME",
	                                                            queue=os.environ.get("PUSH_QUEUE"),
                                                                 kwargs=kwargs)

经过查询celery源码,发现当需要申请新的celery实例的时候,需要将__set_as_current__ 设置为False, 默认为True,为True的时候会重新刷新上下文,但是此时申请的celery实例并没有flask的上下文,所以刷新的时候将会走默认值None,在执行完重建work的时候,会拿当前的celery中的上下文,但是当前为None,所以在之后需要上下文的任务执行的时候,就会产生没有flask上下文的错误。

修改方式

将产生问题地方的代码修改为:

 push_celery_app = Celery(__name__, broker=os.environ.get("PUSH_CELERY_BROKER_URL"),  set_as_current=False)

From: xaohuihui 手搓不易,还请star哦!