Як я можу очистити застряглих / несвіжих працівників-ресекерів?


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)}які скасують реєстрацію лише тих працівників, котрий не є частиною відомих запущених програм. Я не знаю, чи працює це у будь-якому середовищі, але це добре працює на 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}

EDIT

Дуже багато людей підтримують цю відповідь, і я вважаю, що важливо, щоб люди спробували рішення hagope, яке відреєструє працівників із черги, тоді як вищевказаний код видаляє черги. Якщо ви раді їх підробляти, то охолодіть.


3
Якщо він зробить це, він видалить усю чергу, він просто хоче видалити застряглі ..
jBeas

1
Невелике оновлення: тепер вам доведеться використовувати Resque.redis.del замість Resque.redis.delete
James P McGrath

1
Зараз насправді існує метод Resque.remove_queue ()
iainbeeston

28

У вас, мабуть, встановлений дорогоцінний камінь, тож ви можете відкрити консоль і отримати поточних працівників

Resque.workers

Він повертає список робітників

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

виберіть працівника і prune_dead_workers, наприклад, першого

Resque.workers.first.prune_dead_workers

1
Насправді, з другої спроби, це нічого не зробило.
Шпігфорд

2
Це чудово підходить для усунення загиблих працівників, які були вбиті без реєстрації.
Лукас Еклунд

3
Це здається новою найкращою відповіддю, оскільки вона не скасує реєстрацію всіх. Чи не повинні prune_dead_workers бути методом класу? Але в будь-якому випадку чудове рішення! Дякую.
Брайан Армстронг

Це безумовно рішення для вбитих -9 робітників. Єдине, що я хотів би додати, це те, що вам потрібно зробити це на тому ж сервері, де ви вбили з -9.
Погребняк Станіслав Олександрович

Зробіть це всім відразу: Resque.workers.each (&: prune_dead_workers)
Лев

25

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

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

У мене постійно працює колекція завдань, пов’язаних з Resque, що я також додав до цього: https://gist.github.com/ewherrmann/8809350


3
Точки, що показують, як отримати доступ до часу початку роботи за допомогою обробки ['run_at']. Я бачив інші рішення, які використовують метод .started, але це фактично повертає час, коли було розпочато робітник , а не роботу, що є неправильним підходом до звільнення застряглих працівників. Дякую!
Лаклан Коттер

10

Запустіть цю команду там, де ви запустили команду для запуску сервера

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

ви повинні побачити щось подібне:

92102 resque: Processing ProcessNumbers since 1253142769

Зверніть увагу на PID (ідентифікатор процесу) у моєму прикладі це 92102

Потім ви можете вийти з процесу 1 з 2 способів.

  • Витончено використовуйте 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.


2

Ось як можна очистити їх з Redis за назвою хоста. Це трапляється зі мною, коли я вивожу з експлуатації сервер, і працівники не виходять витончено.

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

2

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


1

Почав працювати над https://github.com/shaiguitar/resque_stuck_queue/Нещодавно . Це не вирішення питання, як виправити застряглих працівників, але це вирішує питання про вивішування / застрягання, тому я подумав, що це може бути корисним для людей у ​​цій темі. Від README:

"Якщо resque не виконує завдання протягом певного періоду часу, це запустить заздалегідь визначений обробник на ваш вибір. Ви можете використовувати це для надсилання електронної пошти, пейджерського обов'язку, додавання ще працівників, перезапуску resque, надсилання вам txt. .. що б вам не підходило. "

Використовувався у виробництві і до цього часу для мене працює досить добре.


0

У мене тут також застрягли / черстві робітники, або я повинен сказати «робочі місця», бо працівник насправді там і працює добре, це застряглий процес.

Я вибрав жорстоке рішення вбивства роздвоєного процесу "Обробка", оскільки більше 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 роки тому, коли він показував застряглі завдання, які неможливо видалити за допомогою інтерфейсу, і немає ніякого чистого способу зробити це в рейках
Андрій R

0

Якщо ви використовуєте новіші версії Resque, вам потрібно буде використовувати наступну команду, оскільки внутрішні API змінилися ...

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

0

Це дозволяє уникнути проблеми, якщо у вас є версія resque, новіша за 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.