Co to jest dobry magazyn sesji dla węzła pojedynczego hosta.aplikacja js production?

Używam oprogramowania pośredniczącego Express W / Connect Node. Magazyn sesji pamięci Connect nie nadaje się do produkcji:

Warning: connection.session() MemoryStore is not designed for a production environment, as it will leak memory, and obviously only work within a single process.
W przypadku większych wdrożeń mongo lub redis ma sens.

Ale jakie jest dobre rozwiązanie dla aplikacji z jednym hostem w produkcji?

Author: Nils, 2012-01-06

8 answers

Spędziłem cały dzień przyglądając się temu. Oto opcje, które odkryłem. Requests / second są wykonywane przez ab -n 100000 -c 1 http://127.0.0.1:9778/ na mojej lokalnej maszynie.

  • no sessions-fast (438 req/sec)
  • cookieSession : nie wymaga zewnętrznej usługi, niewielki wpływ na szybkość (311 req / sec) - najszybszy, sesje wygasną z ciasteczkiem (dostosowane przez maxAge)
  • connect-redis : wymaga serwera redis, duży wpływ prędkości (4 req / s z redis2go i redisgreen) - szybciej w przeciwieństwie do mongo, sesje zostaną usunięte po pewnym czasie (dostosowane przez ttl)
  • connect-mongo - wymaga serwera mongodb, duży wpływ na szybkość (2 req / s z mongohq) - wolniejszy niż redis, wymaga ręcznego ustawienia clear_interval do czyszczenia sesji

Oto coffeescript, którego użyłem do gotowania:

server.use express.cookieSession({
    secret: appConfig.site.salt
    cookie: maxAge: 1000*60*60
})

Oto coffeescript, którego używam do redis:

RedisSessionStore ?= require('connect-redis')(express)
redisSessionStore ?= new RedisSessionStore(
    host: appConfig.databaseRedis.host
    port: appConfig.databaseRedis.port
    db: appConfig.databaseRedis.username
    pass: appConfig.databaseRedis.password
    no_ready_check: true
    ttl: 60*60  # hour
)
server.use express.session({
    secret: appConfig.site.salt
    cookie: maxAge: 1000*60*60
    store: redisSessionStore
})

Oto moja kawa dla mongo:

server.use express.session({
    secret: appConfig.site.salt
    cookie:
        maxAge: 100*60*60
    store: new MongoSessionStore({
        db: appConfig.database.name
        host: appConfig.database.host
        port: appConfig.database.port
        username: appConfig.database.username
        password: appConfig.database.password
        auto_reconnect: appConfig.database.serverOptions.auto_reconnect
        clear_interval: 60*60  # hour
    })
})
[7]}teraz oczywiście, remote redis i mongo bazy danych będą wolniejsze niż ich lokalne odpowiedniki. po prostu nie mogłem uruchomić lokalnych odpowiedników, zwłaszcza biorąc pod uwagę, że czas instalacji i konserwacji dla mnie był znacznie większy niż to, co byłem gotów zainwestować w porównaniu z hostowanymi zdalnymi alternatywami, coś, co czuję, jest prawdziwe dla innych, dlatego te hostowane zdalne usługi baz danych istnieją w pierwszej kolejności!

Dla lokalnej bazy danych benhmarks, zobacz @ Mustafa ' s answer .

Happy for someone to Edytuj tę odpowiedź , aby dodać swoje lokalne benchmarki baz danych do mieszanki.

 79
Author: balupton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:26

Ponieważ akceptowana odpowiedź polega tylko na łączeniu się ze zdalnymi hostami, oczywiste jest, że zawsze będzie wolniejsza niż localhost. Nawet jeśli jest to następny komputer w domu, odczyt z tego komputera zajęłby milisekundy, ale pamięć lokalna zajmuje tylko nanosekundy. Należy je porównać przy użyciu lokalnie zainstalowanych serwerów.

Oto moje wyniki z mojego lokalnego komputera: widzisz, redis jest prawie tak szybki jak w pamięci pod dużym obciążeniem. Możesz sklonować moje repo, że te kody testowe są dostępne: https://github.com/mustafaakin/express-session-store-benchmark

Concurrency: 1
none       4484.86 [#/sec] 
memory     2144.15 [#/sec] 
redis      1891.96 [#/sec] 
mongo      710.85 [#/sec] 
Concurrency: 10
none       5737.21 [#/sec] 
memory     3336.45 [#/sec] 
redis      3164.84 [#/sec] 
mongo      1783.65 [#/sec] 
Concurrency: 100
none       5500.41 [#/sec] 
memory     3274.33 [#/sec] 
redis      3269.49 [#/sec] 
mongo      2416.72 [#/sec] 
Concurrency: 500
none       5008.14 [#/sec] 
memory     3137.93 [#/sec] 
redis      3122.37 [#/sec] 
mongo      2258.21 [#/sec] 

Używane strony sesji są bardzo prostymi stronami;

app.get("/", function(req,res){
    if ( req.session && req.session.no){
        req.session.no = req.session.no + 1;
    } else {
        req.session.no = 1;
    }
    res.send("No: " + req.session.no);
});

Redis store config:

app.use(express.session({
    store: new RedisStore({
        host: 'localhost',
        port: 6379,
        db: 2,
        }),
    secret: 'hello'
}));

Mongo Store config:

app.use(express.cookieParser());
app.use(express.session({
    store: new MongoStore({
        url: 'mongodb://localhost/test-session'
    }),
    secret: 'hello'
}));
 65
Author: Mustafa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-30 21:30:21

Kolejną dobrą opcją jest memcached. Stany sesji są tracone po ponownym uruchomieniu memcached, ale praktycznie nigdy nie ma ku temu powodu. Pamięć podręczna może być uruchomiona przez cały czas, nawet po ponownym uruchomieniu serwera aplikacji. Dostęp do danych sesji jest praktycznie natychmiastowy, a memcached będzie działać szczęśliwie z dowolną (odpowiednią) ilością pamięci, którą mu podasz. I nigdy nie widziałem Memcached crash (na Linux).

Https://github.com/elbart/node-memcache

Rzeczy, o których należy pamiętać ogólnie o memcached:

  • nigdy nie używaj spacji w kluczach pamięci podręcznej
  • pamiętaj, że istnieje maksymalna długość klucza pamięci podręcznej, w tym prefiks przestrzeni nazw, którego możesz użyć. Jeśli klucz pamięci podręcznej jest zbyt długi, użyj zamiast tego jednokierunkowego skrótu.

Żaden z nich nie powinien być problemem z przechowywaniem sesji; tylko z uogólnionym buforowaniem.

 9
Author: kgilpin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 14:51:47

Wybrałem sklep z sesjami MongoDB używając connect-mongo .

Zainstaluj za pomocą npm install connect-mongo i zastąp istniejący magazyn pamięci za pomocą

app.use(express.session({ store: new MongoStore({ db: 'some-database' }) }));

Automatycznie zarządza stroną bazodanową sesji.

 6
Author: greenimpala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-02 11:37:49

Nadal używałbym Redis nawet do rozwoju lokalnego. Jest to pomocne, ponieważ przechowuje sesję nawet po ponownym uruchomieniu aplikacji węzła, zachowując sesję przeglądarki zalogowaną. Redis domyślnie zapisuje sesję w pamięci, tak samo jak connect pamięci store jest prosty w konfiguracji (po prostu uruchomić go na ekranie wraz z moimi aplikacjami węzła) może obsługiwać wiele aplikacji, Jeśli po prostu użyć innej bazy danych lub wartości sesji w konfiguracji.

 5
Author: Timothy Meade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 05:42:40

Właśnie odkrywam węzeł.sam js, ale jeśli nie musisz przechowywać wielu informacji w obiekcie sesji-możesz chcieć zbadać bezpieczne pliki cookie.

Bezpieczne pliki cookie przechowują informacje o sesji jako część pliku cookie przechowywanego przez przeglądarkę i przekazywanego przy każdym zapytaniu. Są one zaszyfrowane, aby uniemożliwić użytkownikowi sfałszowanie prawidłowego pliku cookie.

Zaletą jest to, że nie musisz utrzymywać stanu na serwerze-To rozwiązanie dobrze skaluje się i jest proste do wdrożenie.

Wadą jest to, że możesz przechowywać tylko do około 4KB i że dane są wysyłane do serwera na każde żądanie (ale możesz mieć wiele fikcyjnych domen wskazujących na twój serwer, więc nie narzucisz tego bagażu na publicznie widoczną statyczną zawartość, na przykład).

Przeszukując sieć wydaje się, że istnieją co najmniej dwie implementacje bezpiecznych plików cookie dla węzła.js. Nie wiem, jak są gotowe do produkcji, chociaż:

Https://github.com/benadida/node-client-sessions/blob/master/lib/client-sessions.js

Https://github.com/caolan/cookie-sessions

 2
Author: nimrodm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 21:41:33

Sprawdź moje benchmarki na https://github.com/llambda/express-session-benchmarks Pokazywanie porównań różnych implementacji sesji.

 1
Author: llambda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-10 17:44:20

Doceniam, że to stare pytanie, ale natknąłem się na nie szukając rozwiązania podobnego problemu. Już zdecydowałem się użyć memcached do przechowywania sesji w Linuksie( z connect-memcached ), ale wymagałem również możliwości uruchamiania w systemie Windows. Spędziłem chwilę próbując znaleźć pamięć sesji dla aplikacji węzła pojedynczego procesu. Redis i Memcached nie wydają się być dobrze obsługiwane w systemie Windows i nie chciałem dodatkowej złożoności ich instalacja.

Znalazłem session-memory-store w innym wątku przepełnienia stosu, który wygląda dobrze, ale znacznie zwiększył rozmiar moich zależności.

Wreszcie znalazłem memorystore w dokumentacji express-session. Pierwotnie brakowało mi go z powodu podobnej nazwy do domyślnej MemoryStore, ale to dokładnie to, czego szukałem:

Express-session full featured memorystore module without przecieki!

Używam teraz connect-memcached podczas uruchamiania w klastrze (tylko na Linuksie) i memorystore podczas uruchamiania pojedynczego procesu (na Linuksie lub Windows).

Uznałem, że warto zamieścić to jako kolejną odpowiedź, na wypadek gdyby ktoś inny popełnił błąd omijając memorystore, tak jak ja na początku.

 0
Author: davidm_uk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-23 15:51:26