Grundlegendes zum Vorabrufen von Sellerie-Aufgaben

79

Ich habe gerade von der Konfigurationsoption CELERYD_PREFETCH_MULTIPLIER( docs ) erfahren . Der Standardwert ist 4, aber (glaube ich) ich möchte das Prefetching deaktivieren oder so niedrig wie möglich halten. Ich habe es jetzt auf 1 gesetzt, was nah genug an dem liegt, wonach ich suche, aber es gibt noch einige Dinge, die ich nicht verstehe:

  1. Warum ist das Prefetching eine gute Idee? Ich sehe keinen Grund dafür, es sei denn, zwischen der Nachrichtenwarteschlange und den Arbeitern besteht eine große Latenz (in meinem Fall werden sie derzeit auf demselben Host ausgeführt und im schlimmsten Fall möglicherweise auf verschiedenen Hosts mit denselben Daten Center). In der Dokumentation werden nur die Nachteile erwähnt, die Vorteile jedoch nicht erläutert.

  2. Viele Leute scheinen dies auf 0 zu setzen und erwarten, dass sie das Prefetching auf diese Weise deaktivieren können (meiner Meinung nach eine vernünftige Annahme). 0 bedeutet jedoch unbegrenztes Vorabrufen. Warum sollte jemand jemals unbegrenztes Prefetching wünschen, beseitigt dies nicht vollständig die Parallelität / Asynchronität, für die Sie eine Task-Warteschlange eingeführt haben?

  3. Warum kann das Prefetching nicht deaktiviert werden? In den meisten Fällen ist es möglicherweise keine gute Idee, die Leistung auszuschalten. Gibt es jedoch einen technischen Grund dafür, dass dies nicht möglich ist? Oder ist es einfach nicht implementiert?

  4. Manchmal ist diese Option mit verbunden CELERY_ACKS_LATE. Zum Beispiel. Roger Hu schreibt: «[…] Oft möchten [Benutzer], dass ein Mitarbeiter nur so viele Aufgaben reserviert, wie untergeordnete Prozesse vorhanden sind. Dies ist jedoch nicht möglich, ohne verspätete Bestätigungen zu ermöglichen. […] »Ich verstehe nicht, wie diese beiden Optionen miteinander verbunden sind und warum eine ohne die andere nicht möglich ist. Eine weitere Erwähnung der Verbindung finden Sie hier . Kann jemand erklären, warum die beiden Optionen miteinander verbunden sind?

Henrik Heimbuerger
quelle

Antworten:

32
  1. Durch das Vorabrufen kann die Leistung verbessert werden. Die Mitarbeiter müssen nicht auf die nächste Nachricht von einem Broker warten, um sie zu verarbeiten. Die einmalige Kommunikation mit einem Broker und die Verarbeitung vieler Nachrichten führt zu einem Leistungsgewinn. Das Abrufen einer Nachricht von einem Broker (auch von einem lokalen) ist im Vergleich zum lokalen Speicherzugriff teuer. Arbeiter dürfen Nachrichten auch stapelweise bestätigen

  2. Das Vorabrufen auf Null bedeutet "keine bestimmte Grenze" und nicht unbegrenzt

  3. Es wird dokumentiert, dass das Festlegen des Vorabrufs auf 1 dem Ausschalten entspricht. Dies ist jedoch möglicherweise nicht immer der Fall (siehe https://stackoverflow.com/a/33357180/71522 ).

  4. Durch das Vorabrufen können Nachrichten stapelweise bestätigt werden. CELERY_ACKS_LATE = True verhindert, dass Nachrichten bestätigt werden, wenn sie einen Mitarbeiter erreichen

mher
quelle
Vielen Dank. 2) Okay, aber warum sollte jemand "kein bestimmtes Limit" wollen? 3) Ich bin mir ziemlich sicher, dass ich immer noch die Meldung "Aufgabe vom Broker erhalten" sehe, bevor die aktuelle Aufgabe abgeschlossen ist.
Henrik Heimbuerger
1
AFAIK: Das Setzen des Vorabrufs auf 1 entspricht nicht dem Ausschalten. Dies ist der niedrigstmögliche Wert (ohne den Quellcode zu hacken) für das Prefetch. Dies ist wiederum die Anzahl der CPUs / Kerne auf dem aktuellen Computer.
Ron Klein
1
@ RonKlein Es ist nicht die Anzahl der CPUs / Kerne, sondern die Anzahl der von Ihnen definierten Sellerie-Arbeiter (die in einigen Fällen gleich sein können, aber normalerweise nicht). Wenn jeder Worker eine einzelne Aufgabe vorab abruft, sie dann ausführt und dann eine andere vorab abruft, entspricht dies dem Deaktivieren des Vorabrufens, sodass IMHO Ihre Aussage falsch ist. (Das System muss immer so viele Aufgaben vorab abrufen, wie es Arbeiter gibt, wenn es alle Arbeiter mit Aufgaben
versorgen
3
Ich denke, CELERYD_PREFETCH_MULTIPLIER auf 1 gesetzt bedeutet im Grunde "holen". Das Vorabrufen wird impliziert, wenn der Wert auf> 1 gesetzt ist. Tatsächlich werden Aufgaben über 1 hinaus "vorab abgerufen".
Tigeronk2
3
Ich habe einige Experimente durchgeführt, und (zumindest mit den Redis Broker) Einstellungen CELERYD_PREFETCH_MULTIPLIER = 1funktioniert nicht deaktivieren Prefetching. Es wird einfach - wie der Name schon sagt - jeweils nur eine Aufgabe vorab abgerufen.
David Wolever
28

Alte Frage, aber ich füge immer noch meine Antwort hinzu, falls es jemandem hilft. Mein Verständnis von einigen ersten Tests war das gleiche wie das in David Wolevers Antwort. Ich habe dies gerade mehr in Sellerie 3.1.19 getestet und -Ofairfunktioniert. Nur, dass es nicht dazu gedacht ist, das Prefetch auf Worker-Node-Ebene zu deaktivieren. Das wird auch weiterhin passieren. Die Verwendung -Ofairhat einen anderen Effekt, der sich auf der Ebene der Poolarbeiter befindet. Um den Prefetch vollständig zu deaktivieren, gehen Sie wie folgt vor:

  1. einstellen CELERYD_PREFETCH_MULTIPLIER = 1
  2. Auf CELERY_ACKS_LATE = Trueglobaler Ebene oder Aufgabenebene festlegen
  3. Verwenden Sie -Ofairbeim Starten der Arbeiter
  4. Wenn Sie die Parallelität auf 1 setzen, ist Schritt 3 nicht erforderlich. Wenn Sie eine höhere Parallelität wünschen, ist Schritt 3 wichtig, um zu vermeiden, dass Aufgaben in einem Knoten gesichert werden, auf dem Aufgaben mit langer Laufzeit ausgeführt werden können.

Weitere Details hinzufügen:

Ich habe festgestellt, dass der Worker-Knoten standardmäßig immer vorab abgerufen wird. Sie können nur steuern, wie viele Aufgaben vorab abgerufen werden CELERYD_PREFETCH_MULTIPLIER. Bei der Einstellung 1 werden nur so viele Aufgaben vorab abgerufen wie die Anzahl der Pool-Worker (Parallelität) im Knoten. Wenn Sie also Parallelität = n hatten, sind die vom Knoten vorab abgerufenen maximalen Aufgaben n.

Ohne die -OfairOption passierte für mich, dass, wenn einer der Pool-Worker-Prozesse eine lange laufende Aufgabe ausführte, die anderen Worker im Knoten auch die Verarbeitung der bereits vom Knoten vorab abgerufenen Aufgaben einstellen würden. Durch die Verwendung -Ofairhat sich das geändert. Obwohl einer der Mitarbeiter im Knoten lange laufende Aufgaben ausführte, hörten andere nicht mit der Verarbeitung auf und verarbeiteten weiterhin die vom Knoten vorab abgerufenen Aufgaben. Ich sehe also zwei Ebenen des Vorabrufens. Eine auf Worker-Node-Ebene. Der andere auf der Ebene der einzelnen Arbeitnehmer. Die Verwendung -Ofairfür mich schien es auf Arbeiterebene zu deaktivieren.

Wie hängt das ACKS_LATEzusammen? ACKS_LATE = Truebedeutet, dass die Aufgabe nur bestätigt wird, wenn die Aufgabe erfolgreich ist. Wenn nicht, würde es wohl passieren, wenn es von einem Arbeiter empfangen wird. Im Falle eines Prefetch wird die Aufgabe zuerst vom Worker empfangen (aus Protokollen bestätigt), aber später ausgeführt . Ich habe gerade festgestellt, dass vorab abgerufene Nachrichten in rabbitmq unter "Nicht bestätigte Nachrichten" angezeigt werden. Ich bin mir also nicht sicher, ob eine Einstellung Trueunbedingt erforderlich ist. Wir hatten unsere Aufgaben aus anderen Gründen sowieso so eingestellt (spätes Bestätigen).

ksrini
quelle
Vielen Dank, dass Sie noch zu dieser Frage beigetragen haben! Könnten Sie etwas mehr Details hinzufügen? Zum Beispiel hat das Schreiben -Ofaireinen "anderen Effekt", aber nicht, wie sich der Effekt unterscheidet. Sie sprechen auch an CELERY_ACKS_LATE, wie andere zuvor, aber bisher hat es niemand geschafft, mir zu erklären, was dieses Attribut mit dem Deaktivieren des Vorabrufs zu tun hat.
Henrik Heimbuerger
Ich hatte das gleiche Problem mit einem Redis-Backend. Ich hatte 4 gleichzeitige Aufgaben ausgeführt und wenn eine anfing zu hängen, warteten die anderen darauf, dass diese beendet war (es würde nicht) - das Töten dieses Arbeiters würde dann anderen erlauben, fortzufahren. Ich hatte es bereits prefetch=1, celery_acks=Trueund als ich es hinzufügte -Ofair, wurde das Problem behoben, bei dem sie auf den hängenden Arbeiter warteten. Leider ist das Problem mit den hängengebliebenen Arbeitern immer noch nicht für mich behoben, und so hängen schließlich alle Arbeiter, aber zumindest tun sie es nicht mehr genau zur gleichen Zeit.
JiminyCricket
18

Nur eine Warnung: Bei meinen Tests mit dem Redis Broker + Celery 3.1.15 sind alle Ratschläge, die ich zum CELERYD_PREFETCH_MULTIPLIER = 1Deaktivieren des Prefetching gelesen habe, nachweislich falsch.

Um dies zu demonstrieren:

  1. einstellen CELERYD_PREFETCH_MULTIPLIER = 1
  2. Stellen Sie 5 Aufgaben in die Warteschlange, die jeweils einige Sekunden dauern (z. B. time.sleep(5)).
  3. Beobachten Sie die Länge der Aufgabenwarteschlange in Redis: watch redis-cli -c llen default

  4. Start celery worker -c 1

  5. Beachten Sie, dass die Warteschlangenlänge in Redis sofort von 5bis abfällt3

CELERYD_PREFETCH_MULTIPLIER = 1 verhindert nicht das Vorabrufen , sondern beschränkt das Vorabrufen einfach auf 1 Aufgabe pro Warteschlange.

-Ofairverhindert trotz der Dokumentation auch nicht das Prefetching .

Ohne den Quellcode zu ändern, habe ich keine Methode gefunden, um das Prefetching vollständig zu deaktivieren.

David Wolever
quelle
1
Wie bereits in anderen Antworten erwähnt CELERY_ACKS_LATE = 1, wird das Vorabrufen effektiv deaktiviert, wenn Sie auch festlegen .
Jodag
11

Ich kann die Antworten von David Wolever nicht kommentieren, da mein Stackcred nicht hoch genug ist. Daher habe ich meinen Kommentar als Antwort formuliert, da ich meine Erfahrungen mit Celery 3.1.18 und einem Mongodb-Broker teilen möchte. Ich habe es geschafft, das Prefetching mit folgendem zu beenden:

  1. CELERYD_PREFETCH_MULTIPLIER = 1zur Selleriekonfiguration hinzufügen
  2. CELERY_ACKS_LATE = Truezur Selleriekonfiguration hinzufügen
  3. Starten Sie den Sellerie-Arbeiter mit folgenden Optionen: --concurrency=1 -Ofair

Wenn Sie CELERY_ACKS_LATE auf den Standardwert setzen, wird der Worker weiterhin vorab abgerufen. Genau wie beim OP verstehe ich den Zusammenhang zwischen Prefetching und Late Acks nicht vollständig. Ich verstehe, was David sagt "CELERY_ACKS_LATE = True verhindert, dass Nachrichten bestätigt werden, wenn sie einen Mitarbeiter erreichen", aber ich verstehe nicht, warum späte Bestätigungen mit dem Prefetch nicht kompatibel sind. Theoretisch würde ein Prefetch immer noch erlauben, spätes Recht zu bestätigen - auch wenn es nicht als solches in Sellerie codiert ist?

Paul-Armand Verhaegen
quelle
2

Mit SQS als Broker habe ich etwas anderes erlebt.

Das Setup war:

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

Nach dem Fehlschlagen der Aufgabe (Ausnahme ausgelöst) war der Worker nicht mehr verfügbar, da die Nachricht sowohl in der lokalen als auch in der Remote-Warteschlange nicht bestätigt wurde.

Die Lösung, die die Arbeiter dazu brachte, weiterhin Arbeit zu verbrauchen, war die Einstellung

CELERYD_PREFETCH_MULTIPLIER = 0

Ich kann nur spekulieren, dass acks_late beim Schreiben des SQS-Transports nicht berücksichtigt wurde

gCoh
quelle
Ich habe eine PR erstellt, die diesen Fall behandelt. Sie wird in Sellerie verfügbar sein == 4.4.0 github.com/celery/celery/pull/5843
gCoh