Wie lösche ich festsitzende / abgestandene Resque-Mitarbeiter?

132

Wie Sie dem beigefügten Bild entnehmen können, habe ich ein paar Arbeiter, die festzustecken scheinen. Diese Prozesse sollten nicht länger als ein paar Sekunden dauern.

Geben Sie hier die Bildbeschreibung ein

Ich bin nicht sicher, warum sie nicht gelöscht werden oder wie sie manuell entfernt werden können.

Ich bin auf Heroku und verwende Resque mit Redis-to-Go und HireFire, um Arbeiter automatisch zu skalieren.

Shpigford
quelle
2
Hallo, halb verwandte Frage: Wie haben Sie das Resque-Web-Dashboard über Heroku erhalten? Ich kann nicht herausfinden, wie ich es öffnen soll.
Aaron Marks

Antworten:

215

Keine dieser Lösungen hat bei mir funktioniert, ich würde dies immer noch in redis-web sehen:

0 out of 10 Workers Working

Schließlich funktionierte dies für mich, um alle Arbeiter zu klären:

Resque.workers.each {|w| w.unregister_worker}
Hagope
quelle
12
Das hat bei mir funktioniert. Es hat alle Arbeiter abgemeldet , was etwas nervig war. Aber das gefolgt von heroku restartschien den Trick zu tun. Es zeigt jetzt die richtige Anzahl von Arbeitern.
Brian Armstrong
Dies hat die Arbeiter von der Weboberfläche entfernt, aber tatsächlich werden sie immer noch als Prozesse
angezeigt
20
Wenn Sie Resque.workers.each {|w| matches = w.id.match(/^[^:]*:([0-9]*):[^:]*$/); pid = matches[1]; w.unregister_worker unless w.worker_pids.include?(pid.to_s)}nur die Worker abmelden möchten, die keine tatsächlichen Prozesse sind (und möglicherweise Jobs verarbeiten), möchten Sie möglicherweise versuchen, die Registrierung der Worker aufzuheben, deren Pids nicht Teil der bekannten laufenden Pids sind. Ich weiß nicht, ob dies in allen Umgebungen funktioniert, aber es funktioniert gut auf Ubuntu. Dies funktioniert möglicherweise nur, wenn sich Ihre Mitarbeiter auf demselben Computer befinden, auf dem Sie diesen Code ausführen.
Roychri
3
Als Option Resque.workers.map &: unregister_worker
AB
Wie kommt es, dass dies keine Überprüfung beinhaltet, ob der Mitarbeiter vor dem Anruf abgemeldet werden sollteunregister_worker ? Gibt es eine Möglichkeit, dies festzustellen?
user5243421
53

In Ihrer Konsole:

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

Andernfalls können Sie versuchen, sie zu fälschen, um sie zu entfernen, mit:

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

BEARBEITEN

Viele Leute haben diese Antwort positiv bewertet, und ich halte es für wichtig, dass die Leute die Lösung von hagope ausprobieren, mit der die Registrierung von Mitarbeitern aus einer Warteschlange aufgehoben wird, während der obige Code Warteschlangen löscht. Wenn Sie glücklich sind, sie zu fälschen, dann cool.

Einfaltspinsel
quelle
3
Wenn er dies tut, wird die gesamte Warteschlange gelöscht, er möchte nur die festgefahrenen entfernen.
jBeas
1
Kleines Update: Sie müssen jetzt Resque.redis.del anstelle von Resque.redis.delete verwenden
James P McGrath
1
Es gibt tatsächlich eine Resque.remove_queue () Methode jetzt
iainbeeston
28

Wahrscheinlich haben Sie das Resque-Juwel installiert, sodass Sie die Konsole öffnen und aktuelle Mitarbeiter abrufen können

Resque.workers

Es gibt eine Liste der Arbeiter zurück

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

Wählen Sie den Arbeiter und prune_dead_workerszum Beispiel den ersten

Resque.workers.first.prune_dead_workers
Shairon Toledo
quelle
1
Tatsächlich hat dies beim zweiten Versuch nichts bewirkt.
Shpigford
2
Dies eignet sich hervorragend zum Entfernen von Resque-Arbeitern, die ohne Abmeldung getötet wurden.
Lukas Eklund
3
Dies scheint die neue beste Antwort zu sein, da nicht alle abgemeldet werden. Sollte prune_dead_workers nicht eine Klassenmethode sein? Aber auf jeden Fall eine tolle Lösung! Vielen Dank.
Brian Armstrong
Das ist definitiv die Lösung für getötete -9 Arbeiter. Das einzige, was ich hinzufügen möchte, ist, dass Sie dies auf demselben Server tun müssen, auf dem Sie mit -9 getötet haben.
Stanislav O. Pogrebnyak
Tun Sie es allen auf einmal: Resque.workers.each (&: prune_dead_workers)
Leo
24

Zusätzlich zur Antwort von Hagope wollte ich in der Lage sein, nur die Registrierung von Arbeitnehmern aufzuheben, die eine bestimmte Zeit lang gearbeitet hatten. Mit dem folgenden Code werden nur Mitarbeiter abgemeldet, die länger als 300 Sekunden (5 Minuten) arbeiten.

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

Ich habe eine fortlaufende Sammlung von Rake-Aufgaben im Zusammenhang mit Resque, die ich auch hinzugefügt habe: https://gist.github.com/ewherrmann/8809350

ewH
quelle
3
Punkte, um zu zeigen, wie über die Verarbeitung ['run_at'] auf die Startzeit des Jobs zugegriffen werden kann. Ich habe andere Lösungen gesehen, die die .started-Methode verwenden, aber dies gibt tatsächlich die Zeit zurück, zu der der Worker gestartet wurde, nicht den Job, was der falsche Ansatz zum Löschen festsitzender Worker ist. Vielen Dank!
Lachlan Cotter
10

Führen Sie diesen Befehl überall dort aus, wo Sie den Befehl zum Starten des Servers ausgeführt haben

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

Sie sollten so etwas sehen:

92102 resque: Processing ProcessNumbers since 1253142769

Notieren Sie sich die PID (Prozess-ID) in meinem Beispiel 92102

Dann können Sie den Prozess auf zwei Arten beenden.

  • Anmutig verwenden QUIT 92102

  • Mit Gewalt verwenden TERM 92102

* Ich bin mir nicht sicher, welche Syntax es ist QUIT 92102oderQUIT -92102

Lassen Sie mich wissen, wenn Sie Probleme haben.

jBeas
quelle
3
In der Linux-Konsole: kill -SIGQUIT 92102
Alexey
6

Ich habe gerade getan:

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

Habe die Liste der Arbeiter.

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

... wobei n der auf Null basierende Index des unerwünschten Arbeiters ist.

user2811637
quelle
2

Ich hatte ein ähnliches Problem, dass Redis die Datenbank auf einer Festplatte speicherte, die ungültige (nicht laufende) Worker enthielt. Jedes Mal, wenn Redis / resque gestartet wurde, erschienen sie.

Beheben Sie dies mit:

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

Stellen Sie sicher, dass Sie Redis und Ihre Resque-Mitarbeiter neu starten.

Joost
quelle
2

Hier erfahren Sie, wie Sie sie anhand des Hostnamens aus Redis entfernen können. Dies passiert mir, wenn ich einen Server außer Betrieb nehme und die Mitarbeiter nicht ordnungsgemäß beendet werden.

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

Ich bin auf dieses Problem gestoßen und habe mich auf den Weg gemacht, viele der Vorschläge hier umzusetzen. Ich entdeckte jedoch, dass die Hauptursache für dieses Problem darin bestand, dass ich den Edelstein redis-rb 3.3.0 verwendete . Ein Downgrade auf redis-rb 3.2.2 verhinderte, dass diese Arbeiter überhaupt stecken blieben.

Will Bryant
quelle
1

Begann vor kurzem mit der Arbeit an https://github.com/shaiguitar/resque_stuck_queue/ . Es ist keine Lösung, um festsitzende Arbeiter zu reparieren, aber es befasst sich mit dem Problem des Aufhängens / Feststeckens von Resque. Ich dachte, es könnte für Leute in diesem Thread hilfreich sein. Aus der README:

"Wenn resque keine Jobs innerhalb eines bestimmten Zeitraums ausführt, wird ein vordefinierter Handler Ihrer Wahl ausgelöst. Sie können damit eine E-Mail senden, Pager-Aufgaben ausführen, weitere Resque-Mitarbeiter hinzufügen, resque neu starten und Ihnen einen Text senden. ..was immer dir passt."

Wurde in der Produktion verwendet und funktioniert bisher ziemlich gut für mich.

Shai
quelle
0

Ich hatte auch hier festgefahrene Arbeiter, oder sollte ich 'Jobs' sagen, weil der Arbeiter tatsächlich noch da ist und gut läuft, ist es der gegabelte Prozess, der feststeckt.

Ich entschied mich für die brutale Lösung, den gegabelten Prozess "Processing" seit mehr als 5 Minuten über ein Bash-Skript zu beenden, dann spawnte der Worker einfach den nächsten in der Warteschlange und alles geht weiter

Schauen Sie sich mein Skript hier an: https://gist.github.com/jobwat/5712437

jobwat
quelle
0

Ich habe sie direkt aus Redis-Cli entfernt. Glücklicherweise ermöglicht redistogo.com den Zugriff von Umgebungen außerhalb von Heroku. Holen Sie sich die ID des toten Arbeiters aus der Liste. Meins war

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

Führen Sie diesen Befehl direkt in redis aus.

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

Sie können redis db überwachen, um zu sehen, was es hinter den Kulissen tut.

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"

Die vorletzte Zeile löscht den Arbeiter.

Andrei R.
quelle
Keine gute Idee. Dadurch werden in Resque keine Aufhebungs-Hooks aufgerufen, kein Fehler und möglicherweise kein Bereinigungscode aufgerufen.
Jeremy
Dies war nützlich bei resque vor 2 Jahren, als festgefahrene Jobs angezeigt wurden, die über die Benutzeroberfläche nicht gelöscht werden konnten, und es keine saubere Möglichkeit gab, dies in Schienen zu tun
Andrei R
0

Wenn Sie neuere Versionen von Resque verwenden, müssen Sie den folgenden Befehl verwenden, da sich die internen APIs geändert haben ...

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

Dies vermeidet das Problem, solange Sie eine neuere Version als 1.26.0 haben:

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

Beachten Sie, dass der aktuell ausgeführte Job nicht beendet wird.

Joakim Kolsjö
quelle
0

Sie können auch den folgenden Befehl verwenden, um alle rescueWorker zu stoppen

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

Referenz von diesem Link

uzaif
quelle