2015-04-26 9 views
18

Ich habe eine Tonne Forschung zu diesem Thema, und ich bin überrascht, ich habe noch nirgendwo eine gute Antwort gefunden.Capture Heroku SIGTERM in Sellerie Arbeiter zum Herunterfahren Arbeiter anmutig

Ich habe eine große Anwendung auf Heroku ausgeführt, und ich habe bestimmte Sellerie Aufgaben, die für eine sehr lange Zeit Verarbeitung ausgeführt werden, und am Ende der Aufgabe speichern Sie ein Ergebnis. Jedes Mal, wenn ich es auf Heroku umsetze, sendet es SIGTERM (und eventuell SIGKILL) und tötet meinen laufenden Arbeiter. Ich versuche, eine Möglichkeit für die Worker-Instanz zu finden, sich selbst ordnungsgemäß herunterzufahren und sich zur späteren Verarbeitung neu einzuordnen, damit wir schließlich das erforderliche Ergebnis speichern können, anstatt die Aufgabe in der Warteschlange zu verlieren.

Ich kann einen Weg nicht finden, der funktioniert, damit der Arbeiter auf SIGTERM richtig hört. Der nächstgelegene ich bekommen habe, das funktioniert, wenn python manage.py celeryd direkt aber NICHT laufen, wenn die Emulation Heroku Vorarbeiter verwenden, ist die folgende:

@app.task(bind=True, max_retries=1) 
def slow(self, x): 
    try: 
     for x in range(100): 
      print 'x: ' + unicode(x) 
      time.sleep(10) 
    except exceptions.MaxRetriesExceededError: 
     logger.error('whoa') 
    except (exceptions.WorkerShutdown, exceptions.WorkerTerminate) as exc: 
     logger.error(u'retrying, ' + unicode(exc)) 
     raise self.retry(exc=exc, countdown=10) 
    except (KeyboardInterrupt, SystemExit) as exc: 
     print 'retrying' 
     raise self.retry(exc=exc, countdown=10) 
    else: 
     return x 
    finally: 
     logger.info('task ended!') 

Wenn ich diesen Sellerie Aufgabe beginnen innerhalb Vorarbeiter laufen und drücken Sie Strg + C, die passiert folgendes:

^CSIGINT received 
22:20:59 system | sending SIGTERM to all processes 
22:20:59 web.1 | exited with code 0 
22:21:04 system | sending SIGKILL to all processes 
Killed: 9 

es ist so klar, dass keine der Sellerie Ausnahmen, noch die KeyboardInterrupt oder SystemExit Ausnahmen ich in anderen Beiträgen gesehen habe, richtig SIGTERM fangen und den Arbeiter herunterzufahren.

Was ist der richtige Weg?

+0

http://celery.readthedocs.org/en/latest/userguide/workers.html?highlight=sigkill#process-signals scheint darauf hinzuweisen, dass der Hauptarbeiter immer SIGTERM abfängt. –

+0

Richtig - gibt es irgendeinen Weg, den Hauptarbeiter zu den Kindern zu bringen? – jdotjdot

+0

Dies ist ein Problem, das ich auch nie eine großartige Lösung gefunden habe. Ich tendiere dazu, es in der Anwendungslogik zu handhaben, indem ich sicherstelle, dass meine Aufgaben idempotent sind, und dass die Verfolgung gestartet und Aufgaben abgeschlossen werden, sodass ich eine bestimmte Aufgabe beim Start meiner Anwendung automatisch neu starten kann. –

Antwort

2

Sellerie war leider nicht sauber abschalten. JE. Ich meine es so. Selleriearbeiter reagieren auf SIGTERM, aber wenn eine Aufgabe unvollständig ist, warten die Worker-Prozesse, um die Aufgabe zu beenden und erst dann zu beenden. In diesem Fall können Sie SIGKILL senden, wenn die Arbeiter nicht in einer angemessenen Zeit herunterfahren, aber in diesem Fall wird ein Informationsverlust eintreten, d. H. Sie wissen möglicherweise nicht, welche Jobs unvollständig geblieben sind.

+0

Da Sie das Task-Ergebnis persistieren können, sollte es möglich sein, den Task-Status usw. auf der Anwendungsebene zu überprüfen und die Situation wiederherzustellen. –

0

Sie können acks_late oder task_acks_late verwenden.

Aufgaben werden quittiert von der Warteschlange nach Aufgabe ausgeführt und nicht erst vor. So wird die Aufgabe respawnen, wenn der Worker ordnungsgemäß heruntergefahren wird.