Jak usunąć zablokowanych / nieaktualnych pracowników Resque?

132

Jak widać na załączonym obrazku, mam kilku pracowników, którzy wydają się utknąć. Te procesy nie powinny trwać dłużej niż kilka sekund.

wprowadź opis obrazu tutaj

Nie jestem pewien, dlaczego nie wyczyszczą się ani jak ręcznie je usunąć.

Jestem na Heroku i używam Resque z Redis-to-Go i HireFire do automatycznego skalowania pracowników.

Shpigford
źródło
2
Cześć, częściowo związane pytanie: w jaki sposób uzyskałeś pulpit nawigacyjny resque-web za pośrednictwem heroku? Nie wiem, jak to otworzyć.
Aaron Marks

Odpowiedzi:

215

Żadne z tych rozwiązań nie zadziałało, nadal widzę to w redis-web:

0 out of 10 Workers Working

Wreszcie pomogło mi to usunąć wszystkich pracowników:

Resque.workers.each {|w| w.unregister_worker}
Hagope
źródło
12
To zadziałało dla mnie. Wyrejestrował wszystkich pracowników, co było nieco denerwujące. Ale to, co nastąpiło, heroku restartzdawało się działać. Teraz pokazuje prawidłową liczbę pracowników.
Brian Armstrong,
To
usunęło
20
Jeśli chcesz wyrejestrować tylko pracowników, którzy nie są faktycznymi procesami (i być może przetwarzającymi zadania), możesz spróbować Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}wyrejestrować tylko tych pracowników, których numery identyfikacyjne nie są częścią znanych działających pidów. Nie wiem, czy to działa w każdym środowisku, ale działa dobrze na ubuntu. Może to działać tylko wtedy, gdy pracownicy są na tym samym komputerze, na którym uruchamiasz ten kod.
roychri
3
Jako opcja Resque.workers.map &: unregister_worker
AB
Dlaczego nie obejmuje to sprawdzenia, czy pracownik powinien zostać wyrejestrowany przed zadzwonieniem unregister_worker? Czy istnieje sposób, aby to ustalić?
user5243421
53

W Twojej konsoli:

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

W przeciwnym razie możesz spróbować udawać, że są zrobione, aby je usunąć, za pomocą:

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

EDYTOWAĆ

Wiele osób zagłosowało za tą odpowiedzią i uważam, że ważne jest, aby ludzie wypróbowali rozwiązanie Hagope, które wyrejestrowuje pracowników z kolejki, podczas gdy powyższy kod usuwa kolejki. Jeśli z przyjemnością je udajesz, spoko.

Prostak
źródło
3
Jeśli to zrobi, usunie całą kolejkę, po prostu chce usunąć zablokowane ..
jBeas
1
Mała aktualizacja: teraz musisz użyć Resque.redis.del zamiast Resque.redis.delete
James P McGrath
1
W rzeczywistości istnieje teraz metoda Resque.remove_queue ()
iainbeeston
28

Prawdopodobnie masz zainstalowany klejnot resque, więc możesz otworzyć konsolę i zdobyć obecnych pracowników

Resque.workers

Zwraca listę pracowników

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

wybierz pracownika i prune_dead_workersnp. pierwszego

Resque.workers.first.prune_dead_workers
Shairon Toledo
źródło
1
Właściwie przy drugiej próbie nic to nie dało.
Shpigford,
2
Działa to świetnie przy usuwaniu pracowników resque, którzy zostali zabici bez wyrejestrowania.
Lukas Eklund
3
Wydaje się, że to nowa najlepsza odpowiedź, ponieważ nie powoduje wyrejestrowania ich wszystkich. Czy prune_dead_workers nie powinno być metodą klasową? Ale w każdym razie świetne rozwiązanie! Dzięki.
Brian Armstrong,
To zdecydowanie rozwiązanie dla zabitych -9 pracowników. Jedyne, co chciałbym dodać, to to, że musisz to zrobić na tym samym serwerze, na którym zabiłeś z -9.
Stanislav O. Pogrebnyak
Zrób to wszystkim na raz: Resque.workers.each (&: prune_dead_workers)
Leo
25

Dodając odpowiedź przez wiedźmę, chciałem móc wyrejestrować tylko pracowników, którzy pracowali przez określony czas. Poniższy kod wyrejestruje tylko pracowników działających przez ponad 300 sekund (5 minut).

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

Mam ciągłą kolekcję zadań Rake związanych z Resque, do których również dodałem: https://gist.github.com/ewherrmann/8809350

ewH
źródło
3
Punkty za pokazanie, jak uzyskać dostęp do czasu rozpoczęcia zadania poprzez przetwarzanie ['run_at']. Widziałem inne rozwiązania wykorzystujące metodę .started, ale w rzeczywistości zwraca to czas rozpoczęcia pracy pracownika , a nie pracę, co jest złym podejściem do usuwania zablokowanych pracowników. Dzięki!
Lachlan Cotter
10

Uruchom to polecenie w każdym miejscu, w którym zostało uruchomione polecenie uruchomienia serwera

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

powinieneś zobaczyć coś takiego:

92102 resque: Processing ProcessNumbers since 1253142769

Zanotuj PID (identyfikator procesu) w moim przykładzie jest to 92102

Następnie możesz zakończyć proces 1 z 2 sposobów.

  • Używaj z wdziękiem QUIT 92102

  • Użyj siły TERM 92102

* Nie jestem pewien składni, to albo QUIT 92102alboQUIT -92102

Daj mi znać, jeśli masz jakieś problemy.

jBeas
źródło
3
W konsoli Linuksa: kill -SIGQUIT 92102
Alexey
6

Właśnie zrobiłem:

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

Mam listę pracowników.

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

... gdzie n jest indeksem niechcianego pracownika liczonym od zera.

user2811637
źródło
2

Miałem podobny problem, że Redis zapisał bazę danych na dysku zawierającą nieprawidłowych (niedziałających) pracowników. Za każdym razem, gdy uruchamiano Redis / resque, pojawiały się.

Napraw to za pomocą:

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

Upewnij się, że ponownie uruchomiłeś Redis i swoich pracowników Resque.

joost
źródło
2

Oto, jak możesz usunąć je z Redis za pomocą nazwy hosta. Dzieje się tak, gdy wyłączam serwer, a pracownicy nie wychodzą z wdziękiem.

Resque.workers.each { |w| w.unregister_worker if w.id.start_with?(hostname) }
Rich Sutton
źródło
2

Natknąłem się na ten problem i zacząłem podążać ścieżką wdrożenia wielu sugestii tutaj. Jednak odkryłem, że główną przyczyną powodującą ten problem było to, że korzystałem z gem redis-rb 3.3.0 . Obniżenie poziomu do redis-rb 3.2.2 zapobiegło przede wszystkim utknięciu tych pracowników.

Will Bryant
źródło
1

Niedawno rozpocząłem pracę nad https://github.com/shaiguitar/resque_stuck_queue/ . To nie jest rozwiązanie, jak naprawić zablokowanych pracowników, ale rozwiązuje problem ponownego zawieszania się / utknięcia, więc pomyślałem, że może to być pomocne dla osób w tym wątku. Z README:

„Jeśli resque nie uruchamia zadań w określonym przedziale czasowym, uruchomi wstępnie zdefiniowany program obsługi, który wybierzesz. Możesz użyć tego do wysłania wiadomości e-mail, obowiązku pagera, dodania większej liczby pracowników, ponownego uruchomienia ponownego utworzenia, wysłania SMS-a. .. cokolwiek ci odpowiada. "

Był używany w produkcji i do tej pory działa całkiem dobrze.

Shai
źródło
0

Miałem tu również utkniętych / nieaktualnych pracowników resque, a może powinienem powiedzieć „praca”, ponieważ pracownik nadal tam jest i działa dobrze, to rozwidlony proces utknął.

Wybrałem brutalne rozwiązanie polegające na zabijaniu rozwidlonego procesu „Przetwarzanie” od ponad 5 minut za pomocą skryptu bash, a następnie pracownik po prostu spawnuje następnego w kolejce i wszystko idzie dalej

spójrz na mój skrypt tutaj: https://gist.github.com/jobwat/5712437

jobwat
źródło
0

Usunąłem je bezpośrednio z redis-cli. Na szczęście redistogo.com umożliwia dostęp ze środowisk spoza heroku. Uzyskaj identyfikator martwego pracownika z listy. Moje było

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

Uruchom to polecenie bezpośrednio w Redis.

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

Możesz monitorować redis db, aby zobaczyć, co robi za kulisami.

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"

Druga ostatnia linia usuwa pracownika.

Andrei R.
źródło
Nie jest to dobry pomysł. To nie wywoła podpowiedzi wyrejestrowania w Resque, nie wywołania błędu i możliwego wyczyszczenia kodu, który mogą mieć ludzie.
Jeremy
Było to przydatne w resque 2 lata temu, kiedy pokazywał zablokowane zadania, których nie można było usunąć za pomocą interfejsu i nie było prostego sposobu na zrobienie tego w railsach
Andrei R
0

Jeśli używasz nowszych wersji Resque, musisz użyć następującego polecenia, ponieważ wewnętrzne interfejsy API uległy zmianie ...

Resque::WorkerRegistry.working.each {|work| Resque::WorkerRegistry.remove(work.id)}
lloydpick
źródło
0

Pozwala to uniknąć problemu, o ile masz wersję resque nowszą niż 1.26.0:

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

Należy pamiętać, że nie pozwala to na zakończenie aktualnie wykonywanego zadania.

Joakim Kolsjö
źródło
0

możesz również użyć poniższego polecenia, aby zatrzymać wszystkich rescuepracowników

sudo kill -9  `ps aux | grep resque | grep -v grep | cut -c 10-16`

odniesienie z tego linku

uzaif
źródło