Wenn wir neu starten oder bereitstellen, erhalten wir eine Anzahl von Resque-Jobs in der fehlgeschlagenen Warteschlange mit Resque::TermException (SIGTERM)
oder Resque::DirtyExit
.
Wir verwenden das neue TERM_CHILD=1 RESQUE_TERM_TIMEOUT=10
in unserer Procfile, so dass unsere Worker-Zeile wie folgt aussieht:
Wir verwenden auch resque-retry
, von dem ich annahm, dass er bei diesen beiden Ausnahmen automatisch erneut versucht? Aber es scheint nicht zu sein.
Ich schätze also zwei Fragen:
Resque::TermException
in jedem Job retten und diesen verwenden, um den Job neu zu planen. Aber gibt es einen sauberen Weg, dies für alle Jobs zu tun? Sogar ein Affenbeet. Danke!
Bearbeiten: Die Fertigstellung aller Aufträge in weniger als 10 Sekunden erscheint nicht sinnvoll. Es scheint so, als müsste es eine Möglichkeit geben, diese Jobs automatisch neu zu ordnen, wenn die Resque :: DirtyExit-Ausnahme ausgeführt wird.
Ich bin auch auf dieses Problem gestoßen. Es stellt sich heraus, dass Heroku das Signal SIGTERM
nicht nur an den übergeordneten Prozess, sondern auch an alle gegabelten Prozesse sendet. Dies ist nicht die Logik, die Resque erwartet, was dazu führt, dass RESQUE_PRE_SHUTDOWN_TIMEOUT
übersprungen wird und Jobs dazu gezwungen werden, ohne Zeit zu versuchen, einen Job zu beenden.
Heroku lässt Arbeiter 30 s ordnungsgemäß herunterfahren, nachdem ein 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, wenn 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 setzen, um korrekt auf SIGTERM
zu reagieren, die an gegabelte Prozesse gesendet werden.
Hier ist ein Juwel, der das Problem anpasst und dieses Problem genauer erklärt:
- Wir konnten in jedem Job manuell von Resque :: TermException retten und diesen verwenden, um den Job neu zu planen. Aber gibt es einen sauberen Weg zu tun? das für alle Jobs? Sogar ein Affenbeet.
Die Ausnahme Resque::DirtyExit
wird ausgelöst, wenn der Job mit dem Signal SIGTERM
beendet wird. Der Job hat nicht die Möglichkeit, die Ausnahme zu erfassen, da Sie hier lesen können.
- Sollte es nicht erneut versuchen, diese automatisch erneut zu versuchen? Kannst du dir irgendeinen Grund vorstellen, warum es nicht wäre?
Sehen Sie nicht, warum es nicht sollte, läuft der Scheduler? Wenn nicht rake resque:scheduler
.
Ich habe einen detaillierten Blogbeitrag zu einigen der Probleme geschrieben, die ich kürzlich mit Resque::DirtyExit
hatte, vielleicht ist es nützlich = & gt; Die Resque Internals verstehen - Resque :: DirtyExit enthüllt
Nehmen Ihre Resque-Jobs länger als 10 Sekunden in Anspruch? Wenn die Aufträge innerhalb von 10 Sekunden nach dem Senden des ersten SIGTERMs abgeschlossen sind, sollte es Ihnen gut gehen. Versuchen Sie, die Aufträge in kleinere Stücke aufzuteilen, die schneller enden.
Außerdem können Sie Ihren Mitarbeiter den Job neu einreihen lassen, indem Sie etwa Folgendes tun: Ссылка
Ich habe auch eine Weile damit 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 der Fehlerwarteschlange entfernt .
Hier ist ein Beispiel für die Rake-Aufgabe Ссылка
Diese Lösung ist eindeutig suboptimal, aber bis heute ist es die beste Lösung, die ich gefunden habe, diese Jobs erneut zu versuchen.
Tags und Links heroku resque resque-retry