2016-12-27 5 views
1

Wie meine Anwendung strukturiert ist Der node.js-Server sendet Daten an einen Python-Worker, der dann ein nichtstoppendes Skript startet. Was wäre der Ansatz, um den Server node.js zu einem späteren Zeitpunkt in der Lage zu halten, das Skript zu stoppen und den Worker für den erneuten Empfang aus der Warteschlange verfügbar zu machen?Wie würde ich ein Rabbitmq Worker Mid Script stoppen?

Antwort

1

Das Geheimnis Verbraucher von den Produzenten zu stoppen ist in der Regel ein Gift Nachricht zu haben.

Einige tun dies durch mehrere Warteschlangen und einige durch eine dedizierte Nachricht verstanden downstream als aufhören zu konsumieren (letzteres funktioniert nur mit einem einzigen Arbeiter).

Wenn Ihr Python-Skript die Giftnachricht sieht, wird es sofort beendet. Der Grund, warum Sie dies in einer separaten Warteschlange wünschen, ist möglicherweise, dass Sie die Nachricht senden müssen, wenn Sie mehrere Worker haben, sodass Sie pro Worker eine exklusive Warteschlange benötigen.

Wenn Sie das Skript starten, ist es vielleicht am besten, die Mitarbeiter einfach laufen zu lassen und sie auf eine Neustartmeldung warten zu lassen.

Sonst könnten Sie einen Observer Worker oder Controller erstellen, der Nachrichten übernimmt und Prozesse wie das Neustarten des Python-Skripts steuert, aber das ist ziemlich kompliziert.

Ich glaube Sellerie tut viel, wenn Sie nach etwas Vorgeprüftem suchen.

BEARBEITEN - Giftmeldung bedeutet wahrscheinlich schon etwas anderes in AMQP. Was ich meine, ist deine eigene Giftnachricht.

Da Sie etwas töten wollen, während es läuft, müssen Sie es auf Broadcast-Art tun.

Für jeden Verbraucher werden Sie tatsächlich zwei Verbraucher pro Python-Skript haben.

Eins, um die tatsächlichen Daten zu akzeptieren, und eins, um Befehle zum Starten und Stoppen des Datenkonsumenten zu empfangen.

Wenn Sie starten möchten Sie eine Broadcast-Nachricht von haben könnte (JSON, aber man könnte verwenden, was Format, das Sie mögen, oder Sie auch AMQP-Header Eigenschaften als auch nutzen könnten)):

{ 
     "command" : "start" 
    } 

Wenn Sie möchten, stoppen Sie den Hersteller eine Meldung wie senden könnte:

{ 
     "command": "stop" 
    } 

Ihr Verbraucher Rückruf, wenn message.command == 'stop' wird sehen.

Sobald Sie diese Nachricht sehen, rufen Sie channel.basicCancel(consumerTag)auf dem Verbraucher, der tatsächlich Daten empfängt sowie tatsächlich töten, was gerade läuft. Das Töten, was auch immer gerade ausgeführt wird, hängt stark von Ihrem Setup ab, so dass ich nicht wirklich darauf eingehen kann, da es ein separater Prozess sein könnte oder ein separater Thread oder ein Event, wenn eine Event Engine verwendet wird. Töten langwierige Prozesse ist inhärent schwierig.

Jedes Python-Skript sollte eine exklusive Warteschlange für den Befehl consumer haben, wenn ein Themenaustausch verwendet wird ODER Sie können einen Fanout-Austausch (auch als Broadcast bezeichnet) verwenden.

Der Datenverbraucher würde eine Warteschlange mit allen anderen Skripten teilen.

+0

Von allem, was ich nachgeschlagen habe, scheint es eine Giftnachricht ist, wenn ein Verbraucher eine Nachricht nicht verarbeiten kann .. Wie würde das einem Verbraucher helfen zu stoppen? Der Verbraucher würde diese Nachricht nicht einmal erhalten, weil er bereits das aktuelle Skript verarbeitet, oder? – joe

+0

Es tut mir leid, dass ich Giftnachricht gesagt habe, da es wahrscheinlich eine offizielle Giftnachricht gibt, die AMQP verwendet. Der Begriff ist überladen. Was ich mit Giftnachricht meine, ist eine benutzerdefinierte Nachricht, die Sie an Ihrem Ende erstellen, die das Ende signalisiert. –

0

Sie können ein Paket wie Sellerie verwenden, um dies mit RabbitMQ als Ihr Broker zu verwalten. Sellerie hat eine revoke() Funktion, die verwendet werden kann, um eine Aufgabe zu beenden.

>> from celery.task.control import revoke 
>> revoke(task_id, terminate=True) 

Da es klingt wie Sie eine Aufgabe bereits in Prozess stoppen wollen - die revoke Anfrage mit der Option beenden auf True gesetzt wird, eine bereits ausgeführte Aufgabe beenden. Dies ist standardmäßig falsch.

Zum Vergleich: http://docs.celeryproject.org/en/latest/userguide/workers.html#commands