Подтвердить что ты не робот

Захват Heroku SIGTERM в рабочих сельдерей, чтобы закончить работника

Я проделал массу исследований по этому вопросу, и я удивлен, что еще не нашел хорошего ответа на этот вопрос.

Я запускаю большое приложение на Heroku, и у меня есть определенные задачи сельдерея, которые работают очень долго, и в конце задачи сохраняют результат. Каждый раз, когда я передислоцирую на Heroku, он отправляет SIGTERM (и в конечном итоге SIGKILL) и убивает моего бегущего работника. Я пытаюсь найти способ, чтобы рабочий экземпляр изящно закрыл себя и снова запустил очередь для последующей обработки, чтобы в конечном итоге мы могли сохранить требуемый результат, а не потерять поставленную задачу.

Я не могу найти способ, который работает, чтобы рабочий прослушивал SIGTERM должным образом. Самый близкий, который я получил, который работает при запуске python manage.py celeryd напрямую, но NOT при эмуляции Heroku с использованием мастера, выглядит следующим образом:

@app.task(bind=True, max_retries=1)
def slow(self, x):
    try:
        for x in range(100):
            print 'x: ' + unicode(x)
            time.sleep(10)
    except exceptions.MaxRetriesExceededError:
        logger.error('whoa')
    except (exceptions.WorkerShutdown, exceptions.WorkerTerminate) as exc:
        logger.error(u'retrying, ' + unicode(exc))
        raise self.retry(exc=exc, countdown=10)
    except (KeyboardInterrupt, SystemExit) as exc:
        print 'retrying'
        raise self.retry(exc=exc, countdown=10)
    else:
        return x
    finally:
        logger.info('task ended!')

Когда я запускаю задачу celery, выполняющуюся внутри мастера и нажимаю Ctrl + C, происходит следующее:

^CSIGINT received
22:20:59 system   | sending SIGTERM to all processes
22:20:59 web.1    | exited with code 0
22:21:04 system   | sending SIGKILL to all processes
Killed: 9

Итак, ясно, что ни один из исключений сельдерея, а также исключения KeyboardInterrupt или SystemExit, которые я видел в других сообщениях, правильно улавливают SIGTERM и закрывают рабочего.

Каков правильный способ сделать это?

4b9b3361

Ответ 1

сельдерей, к сожалению, не был предназначен для чистого выключения. КОГДА-ЛИБО. Я серьезно. работники сельдери отвечают на SIGTERM, но если задача неполна, рабочие процессы будут ждать, чтобы закончить задачу и только затем выйти. В этом случае вы можете отправить SIGKILL, если работники не закрываются в разумные сроки, но в этом случае будет потеря информации, то есть вы не можете знать, какие задания остались неполными.

Ответ 2

Вы можете использовать acks_late или task_acks_late.

Задачи будут подтверждены из очереди после завершения задачи, а не только до этого. Таким образом, задание будет возрождаться, если рабочий корректно завершит работу.

Ответ 3

Начиная с версии> = 4, Celery поставляется со специальной функцией, предназначенной только для Heroku, которая поддерживает эту функцию сразу после установки:

$ REMAP_SIGTERM=SIGQUIT celery -A proj worker -l info

источник: https://devcenter.heroku.com/articles/celery-heroku#using-remap_sigterm