2013-02-25 3 views
9

Beim Neustart oder bei der Bereitstellung erhalten wir eine Anzahl von Resque-Jobs in der fehlgeschlagenen Warteschlange mit Resque::TermException (SIGTERM) oder Resque::DirtyExit.Sicheres Wiederherstellen von Resque :: TermException oder SIGTERM auf Heroku

wir die neue TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10 in unserem procfile verwenden, damit unsere Arbeiter Linie wie folgt aussieht:

worker: TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10 bundle exec rake environment resque:work QUEUE=critical,high,low 

Wir auch resque-retry mit denen dachte, ich könnte Auto-Wiederholung auf diese beiden Ausnahmen? Aber es scheint nicht zu sein.

Also ich denke, zwei Fragen:

  1. Wir manuell von Resque::TermException in jedem Job retten konnte, und dies den Job neu zu planen nutzen. Aber gibt es einen sauberen Weg, dies für alle Jobs zu tun? Sogar ein Affenfleck.
  2. Sollte es nicht erneut versuchen, diese automatisch erneut zu versuchen? Kannst du dir irgendeinen Grund vorstellen, warum es nicht wäre?

Vielen Dank!

Bearbeiten: Alle Jobs in weniger als 10 Sekunden abgeschlossen zu sein scheint unverhältnismäßig im Maßstab. Es scheint so, als müsste es eine Möglichkeit geben, diese Jobs automatisch neu einzureihen, wenn die Resque :: DirtyExit-Ausnahme ausgeführt wird.

Antwort

1

Betragen Ihre Resque-Jobs länger als 10 Sekunden? Wenn die Aufträge innerhalb von 10 Sekunden nach dem Senden des ursprünglichen SIGTERM abgeschlossen sind, sollte alles in Ordnung sein. Versuchen Sie, die Aufträge in kleinere Stücke aufzuteilen, die schneller enden.

Auch können Sie Ihre Arbeiter wieder enqueue den Job haben so etwas wie dies zu tun: https://gist.github.com/mrrooijen/3719427

+0

upvoted und akzeptiert - ich bin ehrlich gesagt nicht sicher, ob wir sie alle unter 10 Sekunden, obwohl erhalten. Wir haben einige große Exporte usw., die eine Datei erzeugen müssen. Re-Enqueueing scheint das zu lösen? Können Sie den Unterschied zwischen 'Resque :: TermException' und' Resque :: DirtyExit' teilen? Ich habe dort eine Rettung für 'Resque :: DirtyExit', aber es scheint nicht immer wieder in die Warteschlange zu kommen. Vielen Dank! –

+0

Als ein Update retten sie diese Ausnahmen seltsamerweise manchmal nicht sauber, obwohl sie 'resize Resque :: DirtyExit' im Job haben. Ich konnte nicht herausfinden warum. Dies macht unsere Jobs unzuverlässig, da wir sie immer noch mit Resque :: DirtyExit-Ausnahmen in der fehlgeschlagenen Warteschlange finden. Es wird wirklich ein Problem –

+0

Kann jemand empfehlen, wie der Arbeiter das SIGTERM innerhalb des Arbeiters behandeln sollte, also kann der Arbeiter sich sauber schließen? Soll der (Resque-) Worker beispielsweise auch SIGTERM abfangen und eine Variable festlegen, die der Schleifencode regelmäßig überprüft? Ich gehe davon aus, dass die TermException oder DirtyException nur nach RESQUE_TERM_TIMEOUT gesendet wird. –

1
  1. Wir manuell aus Resque :: TermException in jedem Job retten konnte, und verwenden Sie diese um den Auftrag neu planen . Aber gibt es einen sauberen Weg, um dies für alle Jobs zu tun ? Sogar ein Affenfleck.

Die Resque::DirtyExit Ausnahme ausgelöst wird, wenn der Job mit dem SIGTERM Signal getötet wird. Der Job hat nicht die Möglichkeit, die Ausnahme abzufangen, wie Sie können read here.

  1. Sollte nicht resque-retry diese automatisch wiederholen? Kannst du dir irgendeinen Grund vorstellen, warum es nicht wäre?

Nicht sehen, warum es nicht sollte, läuft der Scheduler? Wenn nicht rake resque:scheduler.

ich einen ausführlichen Blog-Eintrag um einige der Probleme habe ich mit Resque::DirtyExit vor kurzem hatte, vielleicht ist es sinnvoll =>Understanding the Resque internals – Resque::DirtyExit unveiled

0

ich damit habe auch für eine Weile zu kämpfen, ohne eine zuverlässige Lösung zu finden.

Eine der wenigen Lösungen, die ich gefunden habe, ist das Ausführen einer Rake-Aufgabe nach einem Zeitplan (Cron-Job alle 1 Minute), der nach Jobs sucht, die mit Resque :: DirtyExit fehlschlagen, diese spezifischen Jobs wiederholt und diese Jobs aus dem Fehler entfernt Warteschlange.

Hier ist eine Probe der Rake Aufgabe https://gist.github.com/CharlesP/1818418754aec03403b3

Diese Lösung deutlich suboptimal ist, aber es ist die beste Lösung, die ich gefunden habe, diese Arbeitsplätze auf dem neuesten Stand wiederholen.

2

Ich stieß auch auf dieses Problem. Es stellt sich heraus, dass Heroku das Signal SIGTERM nicht nur an den übergeordneten Prozess, sondern an alle gegabelten Prozesse sendet. Dies ist nicht die Logik, die Resque erwartet, die dazu führt, dass die RESQUE_PRE_SHUTDOWN_TIMEOUT übersprungen wird, wodurch die Ausführung von Jobs ohne Zeitaufwand für den Abschluss eines Jobs erzwungen wird.

Heroku gibt Arbeiter 30s, um ordnungsgemäß herunterzufahren, nachdem eine SIGTERM ausgegeben wurde. In den meisten Fällen ist dies ausreichend Zeit, um einen Job mit einer gewissen Pufferzeit zu beenden, um den Job an Resque zurückzugeben, falls der Job nicht abgeschlossen werden konnte. Für diese ganze Zeit müssen Sie jedoch RESQUE_PRE_SHUTDOWN_TIMEOUT und RESQUE_TERM_TIMEOUT env vars sowie Patch Resque einstellen, um korrekt auf zu antworten, die an gegabelte Prozesse gesendet werden.

Hier ist ein Juwel, die resque Patches und erklärt, dieses Problem im Detail:

https://github.com/iloveitaly/resque-heroku-signals

+0

Dies ist die korrekte Erklärung. Danke @iloveitaly – Yoni