Verwenden von MemoryStore in der Produktion


116

Heute habe ich meine Node.js-Anwendung zum ersten Mal im "Produktions" -Modus ausgeführt und diese Warnung erhalten:

Warning: connection.session() MemoryStore is not
designed for a production environment, as it will leak
memory, and obviously only work within a single process.

Ich muss nur einen einzigen Prozess ausführen, aber was soll ich stattdessen verwenden? Ich möchte, dass sich meine Sitzungen für einen schnellen Zugriff im RAM befinden. Ich möchte auch in der Lage sein, alle Sitzungen zu verwerfen, indem ich einfach die Node-App herunterfahre.

Es scheint ein Overkill zu sein, Redis, MongoDB oder eine andere Datenbank nur für diese einfache Aufgabe zu installieren. Ich verstehe auch nicht, warum MemoryStore in Node enthalten ist, wenn es nicht wirklich verwendet werden sollte.

Antworten:


29

MemoryStore ist nur für den (schnellen) Entwicklungsmodus vorgesehen, da beim Neustart Ihrer App (Prozess stirbt) alle Sitzungsdaten (die sich im Speicher dieses Prozesses befinden) verloren gehen.

Wenn Sie keine Datenbank verwenden möchten, verwenden Sie stattdessen den verschlüsselten Cookie-Speicher.

http://www.senchalabs.org/connect/cookieSession.html


80

Ok, nachdem ich mit Connect-Entwicklern gesprochen habe, habe ich weitere Informationen erhalten. Hier werden zwei Dinge als Speicherlecks betrachtet:

  1. Problem mit der JSON-Analyse, das bereits in neueren Versionen behoben wurde
  2. die Tatsache, dass abgelaufene Sitzungen nicht bereinigt werden, wenn die Benutzer nie darauf zugreifen (dh die einzige Bereinigung ist der On-Access)

Die Lösung scheint ziemlich einfach zu sein, zumindest habe ich vor, dies zu tun: Verwenden Sie setInterval, um die abgelaufenen Sitzungen regelmäßig zu bereinigen. MemoryStore bietet all (), um die Liste abzurufen, und wir können get () verwenden, um das Lesen zu erzwingen und sie somit ablaufen zu lassen. Pseudocode:

function sessionCleanup() {
    sessionStore.all(function(err, sessions) {
        for (var i = 0; i < sessions.length; i++) {
            sessionStore.get(sessions[i], function() {} );
        }
    });
}

Rufen Sie jetzt einfach sessionCleanup regelmäßig über setInterval () auf und Sie haben die automatische Speicherbereinigung für abgelaufene Sitzungen. Keine Speicherlecks mehr.


3
Ich entdeckte, dass Sie Redis und Mongo auch als Hintergrundgeschäft verwenden und von der Datenbank bereinigen lassen können. Im Fall von Mongo können Sie das Ablaufdatum festlegen und gleichzeitig die Indizierung sicherstellen.
Huggie

57
Es ist wirklich eine dumme Sache, die sie getan haben, indem sie diese Nachricht dort platziert haben. Es ist wie "Wir hätten es richtig machen können, aber stattdessen machen wir es einfach falsch und du spielst ein Ratespiel im Internet. Ha ha! Verlierer!"
Katamphetamin

2
Was ist der Wert des var sessionStore?
Dimitri Kopriwa

4
sessionStore? Ist das eine globale Variable von node.js. Wenn nicht, wie kann ich einen Verweis auf den Sitzungsspeicher in node.js erhalten?
Windspiel

1
@MilanBabuskov - fügst du das in deine app.jsDatei ein? Gibt es eine Option, um innerhalb einer Express-Sitzung einen Rückruf zu tätigen? Ein bisschen mehr Details darüber, wie dies umgesetzt werden kann, wären großartig.
Jonathan Bechtel

46

Die akzeptierte Antwort darauf ist [edit: was] so ziemlich ein Hack, und die anderen empfehlen nur die Verwendung einer Datenbank, die ich für übertrieben halte.

Ich hatte das gleiche Problem und habe gerade die Express-Sitzung durch eine Cookie-Sitzung ersetzt .

Installieren Sie dazu einfach cookie-session:

npm install cookie-session

app.jsFinden Sie dann in Ihrem , wo verwendet express-sessionwird, und ersetzen Sie durch cookie-session.

app.use(require('cookie-session')({
    // Cookie config, take a look at the docs...
}));

Möglicherweise müssen Sie einige andere Dinge ändern, denn für mich war es ein einfacher Swap-Out-Bob-Ihr-Onkel-kein-Schaden-getan.


2
wie hast du das gemacht.
Sid

2
Dies ist eigentlich eine Antwort, die nützlich ist. Danke.
Smonff

5
Der Unterschied besteht darin, dass cookie-sessiondie Daten auf dem Client express-sessiongespeichert werden , während die Daten auf dem Server gespeichert werden.
George

11

Dieses Modul wurde entwickelt, um das Problem des Speicherverlusts zu lösen. https://www.npmjs.com/package/session-memory-store

Die akzeptierte Antwort kann in Ordnung sein. Da diese Frage jedoch ganz oben in der Liste der Suchergebnisse steht, dachte ich, ich würde sie einschließen, falls sie jemand anderem hilft.


Ich habe es noch nicht versucht, aber es scheint eine großartige Lösung für die Situation zu sein (wenn OP mit verlorenen Sitzungen beim Neustart der App in
Ordnung ist

Aus Ihrem Link: "Es wird dringend empfohlen, es in der Produktion zu verwenden!". Die Frage bezieht sich auf "Verwenden von MemoryStore in der Produktion".
Damien

Richtig, aber nur, weil "Sie die Sitzung nicht mit anderen Prozessen oder anderen Diensten teilen können". Das heißt, es gibt andere praktischere Lösungen. Dies löst jedoch das Problem mit dem Speicherverlust. Wenn dies für Sie kein Problem darstellt, ist es in Ordnung, das Problem in der Frage zu verwenden und zu beheben.
Dovev Hefetz

7

Ich denke, der Konsens im Internet ist, dass der richtige Weg darin besteht, tatsächlich eine Datenbank dafür zu verwenden, aber wenn Sie sicher sind, dass Sie das nicht tun möchten, dann unterdrücken Sie die Warnung - die Warnung ist kein Gesetz.

Da Sie und ich uns jedoch einig sind, dass der Speicherverlust ein echtes Problem darstellt, ist es schwer zu rechtfertigen, dass Redis übertrieben ist, da dies Ihr Problem lösen würde.

Ich verstehe auch nicht, warum MemoryStore in Node enthalten ist, wenn es nicht wirklich verwendet werden sollte

Das ist ein großartiger Punkt - aber dazu würde ich sagen, dass der Knoten selbst erst vor kurzem selbst produktionsbereit geworden ist . Einige Leute würden der Vorstellung, dass es überhaupt so ist, nicht zustimmen.


2
Durch Unterdrücken der Warnung wird der Speicherverlust nicht behoben.
Milan Babuškov

lol deshalb raten sie davon ab, es in der Produktion zu verwenden. Die Alternative besteht also darin, eine alternative Speichermethode zu verwenden, nicht wahr?
Kristian

1
Ich glaube, ich mag die Alternativen, die ich bisher gefunden habe, einfach nicht. Ich suche nach einer einfachen In-Memory-Javascript-Alternative, nicht nach einem Datenbanksystem. Ich verstehe wirklich nicht, warum sie es nicht reparieren. Ich meine, wie schwer kann ein einfacher Speicher sein ... Ich hoffe nur, dass es bereits jemand getan hat, damit ich das Rad nicht neu erfinden muss.
Milan Babuškov

2
Ich fühle deinen Schmerz, aber der Knoten ist im Moment ziemlich auf dem neuesten Stand. Er kommt irgendwie mit dem Territorium
Kristian

7
MemoryStore ist nicht in Node enthalten, es ist in Express / Connect
Mustafa

6

Die Alternative ist, Redis oder Mongo als Geschäft zu verwenden. Mit Mongo verwenden Sie das Express-Session-Mongo- Modul.

Es gibt einen Rat, veraltete Sitzungen mit einer Indizierungsoption zu entfernen:

var MongoStore = require('express-session-mongo');
app.use(express.session({ store: new MongoStore() }));

db.sessions.ensureIndex( { "lastAccess": 1 }, { expireAfterSeconds: 3600 } )

Da veraltete Sitzungen von der Datenbank selbst entfernt werden, muss die Express-Sitzung die Bereinigung nicht selbst durchführen.

BEARBEITEN : Es scheint, als müssten Sie ein eigenes Feld "lastAccess" haben. Wenn Sie darauf zugreifen, aktualisieren Sie dieses Feld selbst. Überprüfen Sie die MongoDB Dokumentation expire-Daten http://docs.mongodb.org/manual/tutorial/expire-data/

EDIT2 :

Jetzt wird db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

Der Mongo-Hintergrundthread zum Überprüfen dieses Felds wird alle 60 Sekunden ausgeführt. Der Zeitpunkt zum Entfernen des Dokuments ist also nicht genau.


2

Für diejenigen, die Probleme mit Redis haben, versuchen Sie Folgendes: Ich hoffe, dies hilft.

Ich verwende Redis für DEV und PROD und ziele auf Express v4 ab. Unter Windows verwende ich das leichtgewichtige Toolset MSOpenTech Redis v3.0, ansonsten verwende ich nur das Heroku Redis Addon. Es war nicht allzu schwer, es über Node zum Laufen zu bringen - bis jetzt ...

var session = require('express-session');

. . .

var RedisStore = require('connect-redis')(session);

var redisClient = require('redis').createClient(process.env.REDIS_URL);

var redisOptions = { 
        client: redisClient, 
        no_ready_check: true,
        ttl: 600,
        logErrors: true
};

var redisSessionStore = new RedisStore(redisOptions);

app.use(session({
    store: redisSessionStore,
    secret: 'Some.Long.Series.of.Crazy.Words.and.Jumbled.letter.etc',
    resave: true,       
    saveUninitialized: true 
}));

Viel Glück!

ps. Ich habe gerade erst die ursprüngliche Abfrage erneut gelesen und dies bemerkt - sorry!

Es scheint ein Overkill zu sein, Redis, MongoDB oder eine andere Datenbank nur für diese einfache Aufgabe zu installieren.


0

Wenn Sie OSX verwenden, verwenden Sie

brew install memcached

wenn Linux

apt install memcached

Sitzungsnachricht lösen, da die App eine Verbindung zum Memcache-Dienst 127.0.0.1:11211 herstellen kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.