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.


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}

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,


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.


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

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


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.


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.


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.


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) }

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.


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.


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


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.


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)}

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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.