【问题标题】:Heroku + Celery: Critical Worker Timeout (503)Heroku + Celery:关键工人超时 (503)
【发布时间】:2021-12-04 20:39:06
【问题描述】:

我在 Heroku 上部署了一个 Flask 应用,我正在使用 Celery+Redis 进行异步处理。发送请求时未加载测试页面,并收到此错误:

2021-10-17T13:32:59.278920+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/test_route" host=www.mysite.dev request_id=f387a680-dca6-4e20-8f97-7f4d4a45d17b fwd="73.252.142.129,108.162.215.101" dyno=web.1 connect=0ms service=30000ms status=503 bytes=0 protocol=https
2021-10-17T13:32:59.776324+00:00 app[web.1]: [2021-10-17 13:32:59 +0000] [19] [CRITICAL] WORKER TIMEOUT (pid:23)
2021-10-17T13:32:59.778326+00:00 app[web.1]: [2021-10-17 13:32:59 +0000] [23] [INFO] Worker exiting (pid: 23)

我的测试路线:

@main_bp.route('/test_route')
def test_route():
    celery_tasks.test_task.apply_async()

    return render_template('main/test.html')

芹菜任务:

@celery_app.task()
def test_task():
    print('Test task succeeded')

    return 1

工作人员在任务被触发之前看起来很好:

2021-10-17T13:54:28.080039+00:00 app[worker.1]: [2021-10-17 13:54:28,079: INFO/MainProcess] mingle: all alone
2021-10-17T13:54:28.080111+00:00 app[worker.1]: [2021-10-17 13:54:28,080: DEBUG/MainProcess] ^-- substep ok
2021-10-17T13:54:28.080178+00:00 app[worker.1]: [2021-10-17 13:54:28,080: DEBUG/MainProcess] | Consumer: Starting Tasks
2021-10-17T13:54:28.086858+00:00 app[worker.1]: [2021-10-17 13:54:28,086: DEBUG/MainProcess] ^-- substep ok
2021-10-17T13:54:28.086956+00:00 app[worker.1]: [2021-10-17 13:54:28,086: DEBUG/MainProcess] | Consumer: Starting Control
2021-10-17T13:54:28.094411+00:00 app[worker.1]: [2021-10-17 13:54:28,094: DEBUG/MainProcess] ^-- substep ok
2021-10-17T13:54:28.094481+00:00 app[worker.1]: [2021-10-17 13:54:28,094: DEBUG/MainProcess] | Consumer: Starting Gossip
2021-10-17T13:54:28.100571+00:00 app[worker.1]: [2021-10-17 13:54:28,100: DEBUG/MainProcess] ^-- substep ok
2021-10-17T13:54:28.100633+00:00 app[worker.1]: [2021-10-17 13:54:28,100: DEBUG/MainProcess] | Consumer: Starting event loop
2021-10-17T13:54:28.100745+00:00 app[worker.1]: [2021-10-17 13:54:28,100: DEBUG/MainProcess] | Worker: Hub.register Pool...
2021-10-17T13:54:28.101184+00:00 app[worker.1]: [2021-10-17 13:54:28,101: INFO/MainProcess] celery@82da4ee3-bdcc-46c6-b65b-d6221ba1693e ready.
2021-10-17T13:54:28.101315+00:00 app[worker.1]: [2021-10-17 13:54:28,101: DEBUG/MainProcess] basic.qos: prefetch_count->32

  • 我从路由中删除了 celery 任务 (.apply_async) 并确认页面加载没有它
  • 在本地,我在 celery 任务中添加了time.sleep(30),以确认任务已卸载到工作人员,并且在任务仍在运行时加载页面。这按预期工作

我不确定为什么页面加载会在生产中停止,因为异步处理的目的是不阻止请求。我也不确定如何深入挖掘和调试此错误 - 在文档中找不到太多内容。

我在文档中找到了这个:Debugging Request Timeouts,但它只指向长时间运行的任务和无限循环,这里都不是这种情况

【问题讨论】:

    标签: python flask heroku redis celery


    【解决方案1】:

    这可以通过更改 celery_tasks.py 中使用的 celery 应用来解决。

    这不起作用:

    #celery_tasks.py
    
    from celery import Celery
    
    celery_app = Celery()
    
    @celery_app.task()
    def test_task():
        ...
    

    这行得通:

    #celery_tasks.py
    
    from extensions import celery
    
    celery_app = celery
    
    @celery_app.task()
    def test_task():
        ...
    

    地点:

    #extensions.py
    import flask
    from celery import Celery
    
    class FlaskCelery(Celery):
        def __init__(self, *args, **kwargs):
    
            super(FlaskCelery, self).__init__(*args, **kwargs)
            self.patch_task()
    
            if 'app' in kwargs:
                self.init_app(kwargs['app'])
    
        def patch_task(self):
            TaskBase = self.Task
            _celery = self
    
            class ContextTask(TaskBase):
                abstract = True
    
                def __call__(self, *args, **kwargs):
                    if flask.has_app_context():
                        return TaskBase.__call__(self, *args, **kwargs)
                    else:
                        with _celery.app.app_context():
                            return TaskBase.__call__(self, *args, **kwargs)
    
            self.Task = ContextTask
    
        def init_app(self, app):
            self.app = app
            self.config_from_object(app.config)
    
    
    celery = FlaskCelery()
    

    __init__.py 使用相同的类

    【讨论】:

      猜你喜欢
      • 2021-11-06
      • 2012-09-22
      • 2015-07-04
      • 2020-12-25
      • 2019-12-27
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 2013-09-25
      相关资源
      最近更新 更多