2013-02-25 2 views
9

Когда мы перезапускаем или развертываем, мы получаем несколько заданий Resque в неудавшейся очереди с Resque::TermException (SIGTERM) или Resque::DirtyExit.Восстановление из Resque :: TermException или SIGTERM на Heroku

Мы используем в нашей PROCFILE новый TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10 поэтому наш работник линия выглядит следующим образом:

worker: TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10 bundle exec rake environment resque:work QUEUE=critical,high,low 

Мы также используем resque-retry, который я думал, что мощь автоматического повтора этих двух исключений? Но, похоже, этого не происходит.

Так что я думаю, два вопроса:

  1. Мы могли бы вручную спасти от Resque::TermException в каждой работе, и использовать это, чтобы перенести работу. Но есть ли чистый способ сделать это для всех рабочих мест? Даже патч обезьяны.
  2. Не следует повторно повторять попытку повторного повтора? Можете ли вы подумать о какой-либо причине, почему это не так?

Спасибо!

Редактировать: Получение всех рабочих мест за менее чем 10 секунд кажется необоснованным по шкале. Кажется, должен быть способ автоматически переупорядочить эти задания при выполнении исключения Resque :: DirtyExit.

ответ

1

Выполнены ли ваши рескские задания более 10 секунд? Если задания завершаются в течение 10 секунд после отправки начального SIGTERM, вы должны быть в порядке. Попытайтесь разбить задания на более мелкие куски, которые заканчиваются быстрее.

Кроме того, вы можете иметь ваш рабочий повторно Епдиеие работу делать что-то вроде этого: https://gist.github.com/mrrooijen/3719427

+0

Upvoted и принято - я честно не уверен, что если мы можем получить их все менее чем за 10 секунд, хотя. У нас есть большой экспорт и т. Д., Которые должны сгенерировать один файл. Re-enqueueing кажется, что он решает это, хотя? Вы можете поделиться тем, что разница между 'Resque :: TermException' и' Resque :: DirtyExit'. У меня есть спасение для 'Resque :: DirtyExit', но оно, похоже, не всегда перезаписывается. Благодаря! –

+0

Как обновление, они странно не спасают эти исключения чисто, иногда, несмотря на то, что в задании выполнено спасение Resque :: DirtyExit. Я не мог понять, почему. Это делает нашу работу ненадежной, поскольку мы все еще находим ее в неудавшейся очереди с исключениями Resque :: DirtyExit. Это действительно становится проблемой. –

+0

Может ли кто-нибудь порекомендовать, как рабочий должен обрабатывать SIGTERM внутри рабочего, чтобы рабочий мог полностью закрыться? Например, должен ли (resque) рабочий также захватить SIGTERM и установить некоторую переменную, которую периодически проверяет код цикла? Я предполагаю, что исключение TermException или DirtyException рельсовое только после RESQUE_TERM_TIMEOUT secnds. –

1
  1. Мы могли бы вручную спасти от Resque :: TermException в каждой работе, и использовать это, чтобы перенести работу , Но есть ли чистый способ сделать это для всех заданий? Даже патч обезьяны.

Resque::DirtyExit возбуждается исключение, когда работа будет убит с SIGTERM сигналом. У задания нет возможности поймать исключение, так как вы можете read here.

  1. Не следует повторно повторять попытку повторного повтора? Можете ли вы подумать о какой-либо причине, почему это не так?

Не понимаю, почему это не должно быть, работает ли планировщик? Если не rake resque:scheduler.

Я написал подробный блог вокруг некоторых из проблем, которые я имел в последнее время с Resque::DirtyExit, может быть полезно =>Understanding the Resque internals – Resque::DirtyExit unveiled

0

Я также боролся с этим на некоторое время, не найдя надежное решение.

Одно из немногих решений, которые я нашел, запускает задачу рейка по расписанию (задание cron каждые 1 минуту), которое ищет неудачные задания с помощью Resque :: DirtyExit, повторяет эти конкретные задания и удаляет эти задания из отказа очередь.

Вот образец передней задачи https://gist.github.com/CharlesP/1818418754aec03403b3

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

2

Я столкнулся с этой проблемой. Оказывается, Heroku отправляет сигнал SIGTERM не только родительскому процессу, но и всем разветвленным процессам. Это не та логика, которую ожидает Resque, которая вызывает пропущение RESQUE_PRE_SHUTDOWN_TIMEOUT, заставляя выполнение заданий без каких-либо попыток завершить работу.

Heroku дает работникам 30-е годы изящно завершить работу после выпуска SIGTERM. В большинстве случаев это достаточно времени, чтобы закончить работу с некоторым оставшимся временем буфера, чтобы выполнить задание Resque, если задание не удалось завершить. Тем не менее, за все это время, которое необходимо использовать, вам необходимо установить RESQUE_PRE_SHUTDOWN_TIMEOUT и RESQUE_TERM_TIMEOUT env vars, а также патч Resque, чтобы правильно ответить на SIGTERM, отправляемый на разветвленные процессы.

Вот драгоценный камень, который исправляет Resque и объясняет этот вопрос более подробно:

https://github.com/iloveitaly/resque-heroku-signals

+0

Это правильное объяснение. Спасибо @iloveitaly – Yoni

Смежные вопросы