Heroku-Fehler R14 (Speicherkontingent überschritten) mit node.js

7

Ich habe festgestellt, dass unsere Knoten-App nach etwa einem Tag keinen Speicher mehr hat. Der Speicher wird von einem Job verbraucht, der ungefähr jede Minute ausgeführt wird, da dies derzeit so ziemlich das einzige ist, was gerade passiert. Wenn ich die App lokal auf meinem Computer ausführe, kann ich sehen, dass die App auch die Speichergrenze erreicht, und dann springt die Speicherbereinigung ein.

Auf Heroku scheint es über die Speichergrenze unserer 1G-RAM-Instanz hinauszugehen, und der GC wird nicht aktiviert. Ich frage mich, ob dies daran liegt, dass der Knoten mit einem höheren Speicherlimit als dem tatsächlichen Dyno konfiguriert ist.

Umformulierung: Ist das Speicherlimit von node.js auf herkou an das Speicherlimit von Dyno gebunden?

Stan Wiechers
quelle
Haben Sie Heroku gefragt, wie ihr System funktioniert?
womble

Antworten:

6

Hier ist die Antwort von Heroku. Sieht so aus, als müssten Sie Konfigurationsänderungen vornehmen und können die sofort einsatzbereite Konfiguration nicht verwenden.

Hallo Stan,

Vielen Dank für die Verknüpfung mit diesen Dokumenten. Ich muss dieses Terminalbeispiel aktualisieren, da ich kürzlich die gesprächige WEB_CONCURRENCY-Ausgabe zum Schweigen gebracht habe. Wir haben die Protokollierung hinzugefügt, als wir die Funktion weitgehend hinzugefügt haben, damit die Leute nicht überrascht sind, dass diese neuen Variablen in ihre Umgebung eindringen.

Um die Werte für Ihre App anzuzeigen, können Sie Folgendes ausführen:

$ heroku run 'echo $ WEB_MEMORY, $ WEB_CONCURRENCY' Lassen Sie mich jedoch klar sein - diese Werte sind nur vorhanden, um zu bestimmen, wie viele gleichzeitige Prozesse von einer Cluster-Knoten-App ausgeführt werden sollen, und selbst dann nur, wenn Sie den Wert WEB_CONCURRENCY in verwenden dein Code. Sie wirken sich überhaupt nicht auf die Binärdatei des Knotens oder seine Standardspeicherzuordnungen oder die Speicherbereinigung aus, die völlig standardmäßige Vanilleversionen sind, die von nodejs.org/dist heruntergeladen wurden:

https://devcenter.heroku.com/articles/node-concurrency#tuning-the-concurrency-level V8 verwendet einen gierigen und faulen Ansatz für die Speicherbereinigung. Darüber hinaus geht V8 standardmäßig davon aus, dass Sie mit etwa 1,5 GB arbeiten müssen (mehr als die 1-GB-Grenze eines 2X-Prüfstands). Sie haben einige Optionen, wenn Sie das Standardspeicherverhalten des Knotens ändern möchten:

  • Manuelles Auslösen der GC, wenn der Speicher ein festgelegtes Limit überschreitet ( https://simonmcmanus.wordpress.com/2013/01/03/forcing-garbage-collection-with-node-js-and-v8/ )

  • Setzen Sie max_old_space_size auf einen niedrigeren Wert als den Standardwert (z. B. Knoten --max_old_space_size = 960). Mehrere Metriken in der v8-Quelle sind an max_old_space_size gebunden, sodass gc dadurch etwas aggressiver werden kann. Der Nachteil ist, dass Ihr Programm abstürzt, wenn Sie den Wert sogar um ein Byte überschreiten.

  • Setzen Sie gc_global auf true, um eine immer globale Erfassung zu erzwingen (standardmäßig false - beachten Sie, dass die globale Erfassung langsamer ist als die standardmäßige mehrphasige Erfassung).

  • Setzen Sie nolazy_sweeping auf true, was den gc auch etwas aggressiver macht.

Beachten Sie, dass es die beste Vorgehensweise ist, diesen Prozess in mehrere Worker aufzuteilen, wenn Sie in einem einzelnen Knotenprozess mehr als 1 GB Arbeitsspeicher haben:

https://github.com/joyent/node/wiki/FAQ#what-is-the-memory-limit-on-a-node-process Cheers, Hunter

Stan Wiechers
quelle
1
Auch --optimize_for_sizescheint Zufälligkeit zu reduzieren, zB web: node --optimize_for_size --max_old_space_size=460 --gc_interval=100 server.js blog.heroku.com/archives/2015/11/10/...
Prototyp