Ist es teuer / effizient, Daten zwischen Prozessen im Knoten zu senden?

7
Mit

Node können Sie untergeordnete Prozesse erstellen und Daten zwischen ihnen senden. Sie könnten es verwenden, um zum Beispiel einen Blockierungscode auszuführen.

Dokumentation sagt "Diese Kindknoten sind noch ganz neue Instanzen von V8. Nehmen Sie mindestens 30ms Start und 10MB Speicher für jeden neuen Knoten an. Das heißt, Sie können nicht viele Tausende von ihnen erstellen."

Ich habe mich gefragt, ob es effizient ist, sollte ich mir über einige Einschränkungen Sorgen machen? Hier ist ein Beispielcode:

%Vor%     
youbetternot 05.12.2014, 17:21
quelle

2 Antworten

26

Die Dokumentation sagt Ihnen, dass das Starten neuer Knotenprozesse (relativ) teuer ist. Es ist unklug zu fork() jedes Mal, wenn Sie arbeiten müssen.

Stattdessen sollten Sie einen Pool lang andauernder Worker-Prozesse verwalten - ähnlich wie bei einem Thread-Pool. Queue bearbeitet Anforderungen in Ihrem Hauptprozess und sendet sie an den nächsten verfügbaren Worker, wenn dieser inaktiv wird.

Dies lässt uns eine Frage über das Leistungsprofil des IPC-Mechanismus des Knotens. Wenn Sie fork() angeben, richtet node automatisch einen speziellen Dateideskriptor für den untergeordneten Prozess ein. Es verwendet dies, um zwischen Prozessen zu kommunizieren, indem JSON mit Zeilenbegrenzung gelesen und geschrieben wird. Grundsätzlich, wenn Sie process.send({ ... }) , Knoten JSON.stringify s es und schreibt die serialisierte Zeichenfolge in die fd. Der empfangende Prozess liest diese Daten bis zu einem Zeilenumbruch, dann JSON.parse s it.

Dies bedeutet notwendigerweise, dass die Leistung stark von der Größe der Daten abhängt, die Sie zwischen Prozessen senden.

Ich habe einige Tests überarbeitet, um eine bessere Vorstellung davon zu bekommen, wie diese Leistung aussieht.

Zunächst habe ich dem Worker eine Nachricht mit N Bytes gesendet, die sofort mit einer Nachricht gleicher Länge geantwortet hat. Ich habe dies mit 1 bis 8 gleichzeitigen Arbeitern auf meinem Quad-Core-hyper-threaded i7 versucht.

Wir können sehen, dass es für den Rohdurchsatz vorteilhaft ist, mindestens zwei Arbeiter zu haben, aber mehr als zwei sind im Grunde egal.

Als nächstes schickte ich eine leere Nachricht an den Arbeiter, der sofort mit einer Nachricht von N Bytes antwortete.

Überraschenderweise machte dies keinen Unterschied.

Schließlich habe ich versucht, dem Worker eine Nachricht mit N Bytes zu senden, die sofort mit einer leeren Nachricht geantwortet hat.

Interessant - die Leistung nimmt bei größeren Nachrichten nicht so schnell ab.

Takeaways

  • Das Empfangen großer Nachrichten ist etwas teurer als das Senden. Für den besten Durchsatz sollte Ihr Master-Prozess keine Nachrichten mit mehr als 1 KB senden und keine Nachrichten mit mehr als 128 Byte empfangen.

  • Bei kleinen Nachrichten beträgt der IPC-Overhead etwa 0,02 ms. Das ist klein genug, um in der realen Welt inkonsequent zu sein.

Es ist wichtig zu erkennen, dass die Serialisierung der Nachricht ein synchroner, blockierender Aufruf ist; Wenn der Overhead zu groß ist, wird der gesamte Knotenprozess eingefroren, während die Nachricht gesendet wird. Dies bedeutet, dass E / A ausgehungert wird und Sie keine weiteren Ereignisse (wie eingehende HTTP-Anforderungen) verarbeiten können. Was ist also die maximale Datenmenge, die über den Knoten IPC gesendet werden kann?

Die Dinge werden über 32 kB sehr unangenehm. (Dies sind per-Nachricht; doppelt zu Roundtrip Overhead.)

Die Moral der Geschichte ist, dass Sie sollten:

  • Wenn die Eingabe größer als 32 kB ist, suchen Sie einen Weg, wie Ihr Mitarbeiter den tatsächlichen Datensatz abrufen kann. Wenn Sie die Daten aus einer Datenbank oder einem anderen Netzwerkstandort abrufen, führen Sie die Anforderung im Worker aus. Lassen Sie den Master die Daten nicht holen und versuchen Sie dann, sie in einer Nachricht zu senden. Die Nachricht sollte nur genügend Informationen enthalten, damit der Mitarbeiter seine Arbeit ausführen kann. Denken Sie an Nachrichten wie Funktionsparameter.

  • Wenn die Ausgabe größer als 32 KB ist, suchen Sie nach einer Möglichkeit, dass der Worker das Ergebnis außerhalb einer Nachricht liefert. Schreiben Sie auf den Datenträger oder senden Sie den Socket an den Worker , damit Sie direkt vom Arbeitsprozess aus antworten können.

    >
josh3736 06.12.2014, 01:48
quelle
0

Dies hängt wirklich von Ihren Serverressourcen und der Anzahl der Knoten ab, die Sie hochfahren müssen.

Als Faustregel gilt:

  • Versuchen Sie, laufende Kinder so oft wie möglich wiederzuverwenden - das spart Ihnen 30ms Start-Zeit
  • Starten Sie nicht unbegrenzte Anzahl von Kindern (1 pro Anfrage zum Beispiel) - Sie werden nicht aus dem RAM
  • ausgehen

Das Messaging selbst ist es relativ schnell, glaube ich. Wäre schön, einige Metriken zu sehen.

Beachten Sie auch, dass wenn Sie eine einzelne CPU haben oder einen Cluster ausführen (mit allen verfügbaren Kernen), es nicht viel Sinn ergibt. Sie haben immer noch eine begrenzte CPU-Kapazität und der Wechselkontext ist teurer als das Ausführen eines einzelnen Prozesses.

    
Eugene Kostrikov 05.12.2014 18:40
quelle

Tags und Links