Как убрать застрявших / устаревших работников Resque?


132

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

введите описание изображения здесь

Я не уверен, почему они не будут очищаться или как их вручную удалить.

Я использую Heroku, использую Resque с Redis-to-Go и HireFire для автоматического масштабирования рабочих.


2
Привет, наполовину связанный вопрос: как вы получили панель управления resque-web через heroku? Кажется, я не могу понять, как его открыть.
Аарон Маркс

Ответы:


215

Ни одно из этих решений у меня не сработало, я бы все равно увидел это в redis-web:

0 out of 10 Workers Working

Наконец, это помогло мне очистить всех рабочих:

Resque.workers.each {|w| w.unregister_worker}

12
Это сработало для меня. Он отменил регистрацию всех рабочих, что немного раздражало. Но это, heroku restartпохоже, помогло. Теперь он показывает правильное количество рабочих.
Брайан Армстронг,

Это
убрало

20
Если вы хотите отменить регистрацию только тех рабочих, которые не являются фактическими процессами (и, возможно, обрабатывающими заданиями), вы можете попробовать, Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}что отменит регистрацию только тех рабочих, pid которых не является частью известных работающих pid. Я не знаю, работает ли это во всех средах, но он хорошо работает в ubuntu. Это может работать, только если ваши рабочие находятся на том же компьютере, на котором вы запускаете этот код.
roychri

3
Как вариант Resque.workers.map &: unregister_worker
AB

Почему это не включает проверку того, следует ли отменить регистрацию работника перед звонком unregister_worker? Есть ли способ это определить?
user5243421

53

В вашей консоли:

queue_name = "process_numbers"
Resque.redis.del "queue:#{queue_name}"

В противном случае вы можете попытаться имитировать их как выполняемые для их удаления с помощью:

Resque::Worker.working.each {|w| w.done_working}

РЕДАКТИРОВАТЬ

Многие люди поддерживают этот ответ, и я считаю, что важно, чтобы люди попробовали решение hagope, которое отменяет регистрацию рабочих из очереди, тогда как приведенный выше код удаляет очереди. Если вы счастливы их подделать, тогда круто.


3
Если он это сделает, вся очередь будет
удалена

1
Небольшое обновление: теперь вам нужно использовать Resque.redis.del вместо Resque.redis.delete
Джеймс П. МакГрат

1
На самом деле теперь есть метод Resque.remove_queue ()
iainbeeston

28

Возможно, у вас установлен Resque Gem, так что вы можете открыть консоль и получить текущие рабочие

Resque.workers

Возвращает список рабочих

#=> [#<Worker infusion.local:40194-0:JAVA_DYNAMIC_QUEUES,index_migrator,converter,extractor>]

выберите работника и prune_dead_workers, например, первого

Resque.workers.first.prune_dead_workers

1
Собственно, со второй попытки это ничего не дало.
Shpigford

2
Это отлично подходит для очистки спасателей, которые были убиты без отмены регистрации.
Лукас Эклунд

3
Это похоже на новый лучший ответ, поскольку он не отменяет регистрацию всех из них. Разве prune_dead_workers не должно быть методом класса? Но в любом случае отличное решение! Спасибо.
Брайан Армстронг

Это определенно решение для убитых -9 рабочих. Единственное, что я хотел бы добавить, это то, что вам нужно сделать это на том же сервере, где вы убили с -9.
Станислав Олегович Погребняк

Сделайте это со всеми сразу: Resque.workers.each (&: prune_dead_workers)
Лев

25

Добавляя к ответу хагопа, я хотел иметь возможность отменять регистрацию только тех рабочих, которые работали в течение определенного времени. Приведенный ниже код отменяет регистрацию только тех рабочих, которые работают более 300 секунд (5 минут).

Resque.workers.each {|w| w.unregister_worker if w.processing['run_at'] && Time.now - w.processing['run_at'].to_time > 300}

У меня есть постоянная коллекция задач Rake, связанных с Resque, к которой я также добавил: https://gist.github.com/ewherrmann/8809350


3
Очки для демонстрации того, как получить доступ к времени начала задания с помощью обработки ['run_at']. Я видел другие решения, в которых используется метод .started, но на самом деле он возвращает время запуска рабочего , а не задание, что является неправильным подходом для очистки застрявших рабочих. Спасибо!
Lachlan Cotter

10

Запустите эту команду везде, где вы запускали команду для запуска сервера

$ ps -e -o pid,command | grep [r]esque

вы должны увидеть что-то вроде этого:

92102 resque: Processing ProcessNumbers since 1253142769

Обратите внимание на PID (идентификатор процесса) в моем примере это 92102

Затем вы можете выйти из процесса одним из двух способов.

  • Изящно использовать QUIT 92102

  • Сильно использовать TERM 92102

* Я не уверен в синтаксисе, либо это QUIT 92102либоQUIT -92102

Сообщите мне, если у вас возникнут проблемы.


3
В консоли Linux: kill -SIGQUIT 92102
Алексей

6

Я только что сделал:

% rails c production
irb(main):001:0>Resque.workers

Получил список рабочих.

irb(main):002:0>Resque.remove_worker(Resque.workers[n].id)

... где n - нулевой индекс нежелательного работника.


2

У меня была похожая проблема, что Redis сохранил БД на диск, который содержал недействительных (не работающих) рабочих. Они появлялись каждый раз при запуске Redis / resque.

Исправьте это, используя:

Resque::Worker.working.each {|w| w.done_working}
Resque.redis.save # Save the DB to disk without ANY workers

Убедитесь, что вы перезапустили Redis и ваши Resque worker.


2

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

Resque.workers.each { |w| w.unregister_worker if w.id.start_with?(hostname) }

2

Я столкнулся с этой проблемой и начал реализовывать здесь множество предложений. Однако я обнаружил, что основная причина этой проблемы заключалась в том, что я использовал гем redis-rb 3.3.0 . Переход на redis-rb 3.2.2 предотвратил застревание этих рабочих процессов.


1

Недавно начал работать над https://github.com/shaiguitar/resque_stuck_queue/ . Это не решение того, как исправить застрявших рабочих, но оно решает проблему зависания / зависания в реске, поэтому я подумал, что это может быть полезно для людей в этой теме. Из README:

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

Используется в производстве и пока работает для меня довольно хорошо.


0

У меня тоже были застрявшие / устаревшие resque-воркеры, или я должен сказать «jobs», потому что воркер на самом деле все еще там и работает нормально, это застрял разветвленный процесс.

Я выбрал жестокое решение - убить разветвленный процесс «Обработка» более 5 минут с помощью сценария bash, затем рабочий просто порождает следующий в очереди, и все продолжает работать

посмотрите мой скрипт здесь: https://gist.github.com/jobwat/5712437


0

Я удалил их напрямую из redis-cli. К счастью, redistogo.com разрешает доступ из окружений за пределами heroku. Получите идентификатор мертвого рабочего из списка. Мой был

55ba6f3b-9287-4f81-987a-4e8ae7f51210:2

Запустите эту команду напрямую в Redis.

del "resque:worker:55ba6f3b-9287-4f81-987a-4e8ae7f51210:2:*"

Вы можете контролировать redis db, чтобы увидеть, что он делает за кулисами.

redis xxx.redistogo.com> MONITOR
OK
1380274567.540613 "MONITOR"
1380274568.345198 "incrby" "resque:stat:processed" "1"
1380274568.346898 "incrby" "resque:stat:processed:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*" "1"
1380274568.346920 "del" "resque:worker:c65c8e2b-555a-4a57-aaa6-477b27d6452d:2:*"
1380274568.348803 "smembers" "resque:queues"

Вторая последняя строка удаляет работника.


Не хорошая идея. Это не вызовет хуки отмены регистрации в Resque, не вызовет сбой и возможный код очистки, который может быть у людей.
Джереми

Это было полезно с resque 2 года назад, когда он показывал зависшие задания, которые невозможно было удалить с помощью интерфейса, и не было чистого способа сделать это в рельсах
Андрей Р

0

Если вы используете более новые версии Resque, вам нужно будет использовать следующую команду, поскольку внутренние API-интерфейсы изменились ...

Resque::WorkerRegistry.working.each {|work| Resque::WorkerRegistry.remove(work.id)}

0

Это позволяет избежать проблемы, если у вас установлена ​​более новая версия восстановления, чем 1.26.0:

resque: env QUEUE=foo TERM_CHILD=1 bundle exec rake resque:work

Имейте в виду, что это не позволяет завершить текущую работу.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.