Używanie MemoryStore w produkcji


116

Dzisiaj po raz pierwszy uruchomiłem moją aplikację Node.js w trybie „produkcyjnym” i otrzymałem następujące ostrzeżenie:

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

Muszę uruchomić tylko jeden proces, ale czego powinienem użyć zamiast tego? Chcę, aby moje sesje znajdowały się w pamięci RAM w celu szybkiego dostępu. Chcę też móc odrzucić wszystkie sesje, po prostu wyłączając aplikację Node.

Instalacja Redis, MongoDB lub innej bazy danych tylko dla tego prostego zadania wydaje się przesadą. Nie rozumiem też, dlaczego MemoryStore jest zawarte w Node, skoro tak naprawdę nie powinno być używane?

Odpowiedzi:


29

MemoryStore służy tylko do (szybkiego) trybu programowania, ponieważ jeśli Twoja aplikacja zostanie ponownie uruchomiona (proces umrze), utracisz wszystkie dane sesji (które znajdowały się w pamięci tego procesu).

Jeśli nie chcesz korzystać z bazy danych, użyj zamiast tego zaszyfrowanego magazynu plików cookie.

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


80

Ok, po rozmowie z programistami Connect, uzyskałem więcej informacji. Istnieją dwie rzeczy uważane za wycieki pamięci:

  1. problem z parsowaniem JSON, który został już naprawiony w ostatnich wersjach
  2. fakt, że nie ma czyszczenia wygasłych sesji, jeśli użytkownicy nigdy nie mają do nich dostępu (tj. jedyne czyszczenie odbywa się przy dostępie)

Rozwiązanie wydaje się dość proste, przynajmniej to planuję zrobić: użyj setInterval, aby okresowo wyczyścić wygasłe sesje. MemoryStore udostępnia all (), aby uzyskać listę, i możemy użyć get (), aby wymusić odczyt, a tym samym wygaśnąć je. Pseudo kod:

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

Teraz po prostu wywołuj sesję sessionCleanup okresowo poprzez setInterval () i masz automatyczne czyszczenie pamięci dla wygasłych sesji. Nigdy więcej wycieków pamięci.


3
Odkryłem, że możesz również użyć Redis i Mongo jako magazynu zapasowego i poprosić DB o wyczyszczenie. W przypadku Mongo możesz ustawić datę wygaśnięcia przy jednoczesnym zapewnieniu indeksowania.
— przytulanie,

57
To naprawdę głupia rzecz, którą zrobili, umieszczając tam tę wiadomość. To jak "Mogliśmy zrobić to dobrze, ale zamiast tego po prostu zrobimy to źle, a ty zagrasz w zgadywanie na internetach. Ha ha! Przegrani!"
— katamfetamina

2
jaka jest wartość var ​​sessionStore?
— Dimitri Kopriwa

4
sessionStore? Czy to jest zmienna globalna node.js? Jeśli nie, w jaki sposób mogę uzyskać odwołanie do magazynu sesji w node.js?
— windchime

1
@MilanBabuskov - czy umieszczasz to w swoim app.jspliku? Czy istnieje możliwość wywołania zwrotnego w ramach sesji ekspresowej? Nieco więcej szczegółów na temat tego, jak to zrobić, byłoby świetne.
— Jonathan Bechtel

46

Więc akceptowaną odpowiedzią na to jest [edit: was] prawie hack, a inni po prostu zalecają użycie bazy danych, która moim zdaniem jest przesada.

Miałem ten sam problem i po prostu zastąpiłem sesję ekspresową sesją cookie .

Aby to zrobić, po prostu zainstaluj cookie-session:

npm install cookie-session

Następnie w swoim app.js, znajdź, gdzie express-sessionjest używany i zamień na cookie-session.

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

Być może będziesz musiał zmienić kilka innych rzeczy, dla mnie była to prosta zamiana-bobs-twojego-wujka-bez szkody.


2
jak to zrobiłeś.
— Sid

2
W rzeczywistości jest to przydatna odpowiedź. Dzięki.
— smonff

5
różnica polega na tym, że cookie-sessionprzechowuje dane na kliencie, podczas gdy express-sessionprzechowuje dane na serwerze.
— George

11

Ten moduł został zaprojektowany, aby radzić sobie z problemem wycieku pamięci. https://www.npmjs.com/package/session-memory-store

Przyjęta odpowiedź może być w porządku. Ponieważ jednak to pytanie pojawia się wysoko na liście wyników wyszukiwania, pomyślałem, że uwzględnię je na wypadek, gdyby komuś innemu pomogło.


Nie próbowałem tego, ale wygląda na to, że jest to świetne rozwiązanie dla tej sytuacji (jeśli OP jest w porządku z utraconymi sesjami po ponownym uruchomieniu aplikacji)
— stujo

Z Twojego linku: „Zdecydowanie nie zaleca się używania go w produkcji!”. Pytanie dotyczy „używania MemoryStore w produkcji”.
— Damien

Zgadza się, ale tylko dlatego, że „nie możesz udostępniać sesji innym procesom lub innym usługom”. Oznacza to, że istnieją inne, bardziej praktyczne rozwiązania. Ale to rozwiązuje problem wycieku pamięci, więc jeśli to nie dotyczy Ciebie, możesz użyć i rozwiązać problem w pytaniu.
— Dovev Hefetz

7

Myślę, że w sieci panuje zgoda co do tego, że właściwym sposobem byłoby rzeczywiście użycie do tego DB, ale jeśli jesteś pewien, że nie chcesz tego robić, zlikwiduj ostrzeżenie - ostrzeżenie nie jest prawem.

Ponieważ jednak oboje zgadzamy się, że wyciek pamięci jest prawdziwym problemem, trudno jest uzasadnić stwierdzenie, że redis to przesada, ponieważ rozwiązałoby to twój problem.

Nie rozumiem też, dlaczego MemoryStore jest zawarte w Node, kiedy tak naprawdę nie powinno być używane

to świetna uwaga - ale powiedziałbym, że sam węzeł dopiero niedawno stał się gotowy do produkcji . Niektórzy ludzie nie zgodziliby się z poglądem, że tak w ogóle jest.


2
Wyłączenie ostrzeżenia nie spowoduje, że wyciek pamięci zniknie.
— Milan Babuškov

lol, dlatego odradzają używanie go w produkcji. więc alternatywą jest użycie innej metody przechowywania, prawda?
— Kristian,

1
Chyba po prostu nie lubię alternatyw, które znalazłem do tej pory. Szukam prostej alternatywy javascript w pamięci, a nie systemu bazy danych. Naprawdę nie rozumiem, dlaczego tego nie naprawią. Chodzi mi o to, jak ciężki może być prosty sklep z pamięcią ... Mam tylko nadzieję, że ktoś już to zrobił, więc nie muszę ponownie wymyślać koła.
— Milan Babuškov

2
Czuję twój ból, ale węzeł jest teraz dość krwawiący ... to jakby pochodzi z terytorium
— Kristian

7
MemoryStore nie jest zawarty w Node, jest zawarty w Express / Connect
— Mustafa

6

Alternatywą jest użycie Redis lub Mongo jako sklepu. W Mongo używasz modułu express-session-mongo .

Istnieje rada dotycząca usuwania przestarzałych sesji za pomocą opcji indeksowania:

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

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

Ponieważ przestarzałe sesje są usuwane przez samą bazę danych, sesja Express nie musi sama zajmować się czyszczeniem.

EDYCJA : Wygląda na to, że musisz mieć własne pole „lastAccess”. Po uzyskaniu do niego dostępu samodzielnie aktualizujesz to pole. Sprawdź dokumentację MongoDB expire-data http://docs.mongodb.org/manual/tutorial/expire-data/

EDYCJA2 :

Teraz staje się db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

Wątek Mongo w tle, aby sprawdzić to pole, jest uruchamiany co 60 sekund. Więc czas usunięcia dokumentu nie jest dokładny.


2

Dla tych, którzy mają problemy z Redis, spróbuj wykonać następujące czynności - miej nadzieję, że to pomoże.

Używam Redis dla DEV i PROD i używam Express v4. W systemie Windows używam lekkiego zestawu narzędzi MSOpenTech Redis v3.0, w przeciwnym razie po prostu używam dodatku Heroku Redis. Uruchomienie go przez Node nie było zbyt trudne - jak dotąd ...

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 
}));

Powodzenia!

ps. Właśnie ponownie przeczytałem pierwotne zapytanie i zauważyłem to - przepraszam!

Instalacja Redis, MongoDB lub innej bazy danych tylko dla tego prostego zadania wydaje się przesadą.


0

Jeśli używasz OSX, użyj

brew install memcached

jeśli linux

apt install memcached

rozwiązać wiadomość sesji, ponieważ aplikacja może łączyć się z usługą memcache 127.0.0.1:11211.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.