2012-01-05 20 views
63

Utilizzo il middleware Node's Express w/Connect. negozio sessione di memoria del Connect non è adatto per la produzione di:Che cos'è un archivio di sessione valido per un'app di produzione Node.js con host singolo?

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

Per le distribuzioni più grandi, Mongo o Redis ha un senso.

Ma quale è una buona soluzione per un'app single-host in produzione?

+1

stavo usando cookie-sessiosn ma ci sono dati sessiosn memorizzati da qualche parte o no perché quello che stava accadendo nel mio caso era che le sessioni correnti venivano mostrate solo ma non quelle precedenti ?? –

risposta

77

Abbiamo passato la giornata a guardare a questo. Ecco le opzioni che ho scoperto. Le richieste/secondo vengono eseguite tramite ab -n 100000 -c 1 http://127.0.0.1:9778/ sul mio computer locale.

  • sessioni - veloce (438 req/sec)
  • cookieSession: non richiede alcun servizio esterno, impatto minore velocità (311 req/sec) - più veloce, sessioni scadranno con il cookie (personalizzato maxAge)
  • connect-redis: richiede Redis del server, grande impatto velocità (4 req/sec con redis2go e redisgreen) - più veloce di Mongo, sessioni saranno cancellati dopo un po '(personalizzato ttl)
  • connect-mongo - richiede server di MongoDB, impatto grande velocità (2 req/sec con mongohq) - più lento di redis, re quaderni manuale clear_interval da impostare per le sessioni di pulizia

Ecco la CoffeeScript che ho usato per cookieSession:

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

Ecco l'CoffeeScript che uso per 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 
}) 

Qui è la mia coffeescript per 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 
    }) 
}) 

Ora, ovviamente, i database redis e mongo remoti saranno più lenti dei loro equivalenti locali. Non riuscivo a far funzionare gli equivalenti locali, soprattutto considerando che il tempo di installazione e manutenzione per me era molto maggiore di quello che ero disposto a investire rispetto alle alternative remote ospitate, qualcosa che ritengo sia vero anche per gli altri perché questi ospitati i servizi di database remoto esistono in primo luogo!

Per il database locale benhmarks, vedere @Mustafa's answer.

Felice che qualcuno possa aggiungere edit this answer ai benchmark del database locale.

+0

Wow, nice vedere i numeri. Certamente influenzato le mie decisioni. Grazie! –

+0

Ouch, sono davvero sorpreso che il provider di redis sia così lento ... – UpTheCreek

+0

A proposito, sarebbe davvero bello vedere MemoryStore confrontato con questi - qualche possibilità? ;) – UpTheCreek

2

Sto solo esplorando node.js personalmente, ma se non è necessario memorizzare molte informazioni nell'oggetto di sessione, è possibile che si desideri esplorare i cookie protetti.

I cookie protetti memorizzano le informazioni sulla sessione come parte del cookie che il browser memorizza e inoltra con ciascuna richiesta. Sono crittografati per impedire a un utente di falsificare un cookie valido.

Il vantaggio è che non è necessario mantenere lo stato sul server: questa soluzione è scalabile e semplice da implementare.

Lo svantaggio è che si può memorizzare solo fino a circa 4 KB e che i dati viene inviato al server su ogni richiesta (Ma si può avere più domini fittizi che indicano al vostro server in modo da non imporre la bagaglio contenuto statico visibile pubblicamente, ad esempio).

Ricerca nel Web sembra che ci siano almeno due implementazioni di cookie sicuri per node.js. Non sicuro come pronti per la produzione sono, però:

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

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

+0

Divertente, Ben Adida è in realtà un mio amico. Mondo piccolo! – Nils

+1

Non sono un esperto, ma ho pensato che il consenso generale è che i cookie sicuri non sono ... be '... sicuri. Farò qualche lettura ma non voglio fare nulla che non sia ancora mainstream. – Nils

+0

Bene, si può sempre andare e implementare un semplice archivio di sessioni basato sui file - qualcosa di simile a ciò che fa PHP. Supponendo che il sistema operativo memorizza nella cache i file, si otterrà una prestazione ragionevole. O potresti usare tmpfs che è un filesystem con memoria. – nimrodm

5

vorrei ancora usare Redis, anche per lo sviluppo locale. Ciò è utile perché memorizza la sessione anche quando si riavvia l'applicazione Node, mantenendo la sessione del browser connessa. Redis salva per impostazione predefinita la sessione in memoria, come se la memoria di connessione di Connect è semplice da configurare (l'ho appena eseguita sullo schermo insieme a le mie app di nodo) possono supportare più applicazioni se si utilizza semplicemente un database diverso o un valore di sessione nella configurazione.

+0

non userei diversi negozi per dev e prod, avrete indubbiamente degli errori non rilevati che lo fanno in questo modo. Tim è corretto, usa redis per local e prod. – chovy

+0

Non molto divertente se si sviluppa su una finestra di windows però. – UpTheCreek

+0

stavo usando cookie-sessiosn ma ci sono dati sessiosn memorizzati da qualche parte o no perché quello che stava accadendo nel mio caso era che le sessioni correnti venivano mostrate solo ma non quelle precedenti ?? –

8

Un'altra buona opzione è memcached. Gli stati della sessione vengono persi se viene riavviato memcached, ma non c'è praticamente mai alcun motivo per farlo. È possibile lasciare la cache sempre in esecuzione anche quando si riavvia il server dell'app. L'accesso ai dati della sessione è praticamente istantaneo e memcached funzionerà felicemente con qualsiasi quantità (appropriata) di memoria che tu gli dai. E non ho mai visto l'arresto in memcached (su Linux).

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

cose da tenere a mente su memcached in generale:

  • non hanno mai spazi bianchi nelle vostre chiavi della cache
  • essere consapevoli del fatto che v'è una lunghezza della chiave massima di cache, incluso qualsiasi namespace prefisso potrebbe usare Se la tua chiave di cache è troppo lunga, usa invece un hash a 1 via.

Nessuno di questi deve essere un problema con l'archiviazione di sessione; solo con il caching generalizzato.

+0

Sai come collegarlo per connettere il gestore di sessione del middleware? (Sono un n00b in questa area) – Nils

+0

No, scusa, non l'ho ancora fatto. – kgilpin

+0

@Chocohound Hai scoperto ... Potrei collegarmi al server Memcache .. ma come posso configurare l'archivio delle sessioni con memcache nel file degli ambienti? – Alan

6

Sono andato con un negozio di sessione MongoDB utilizzando connect-mongo.

installazione con npm install connect-mongo e sostituire il MemoryStore esistente con

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

Gestisce il lato banca dati delle sessioni automaticamente.

64

Poiché la risposta accettata è solo la connessione a host remoti, è ovvio che sarà sempre più lento di localhost. Anche se è il prossimo computer di casa, ci vorranno millisecondi per leggere da quel computer, ma la memoria locale impiega solo nanosecondi. È necessario confrontarli utilizzando server installati localmente.

Ecco i miei risultati dal mio pc locale: Vedete, redis è quasi veloce quanto in memoria in sotto carico elevato.È possibile clonare il mio repo che questi codici di test sono disponibili: 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] 

La sessione utilizzati pagine sono pagine molto semplici;

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 negozio config:

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

Mongo negozio config:

app.use(express.cookieParser()); 
app.use(express.session({ 
    store: new MongoStore({ 
     url: 'mongodb://localhost/test-session' 
    }), 
    secret: 'hello' 
})); 
+0

stavo usando cookie-sessiosn ma ci sono dati sessiosn memorizzati da qualche parte o meno perché quello che stava accadendo nel mio caso era che le sessioni correnti venivano mostrate solo ma non quelle precedenti ?? –

1

controllo fuori i miei punti di riferimento a https://github.com/llambda/express-session-benchmarks che mostrano il confronto di diverse implementazioni di sessione.

+0

stavo usando cookie-sessiosn ma ci sono dati sessiosn memorizzati da qualche parte o no perché quello che stava accadendo nel mio caso era che le sessioni correnti venivano mostrate solo ma non quelle precedenti ?? –

0

Apprezzo che questa è una domanda vecchia, ma l'ho trovata mentre cercavo una soluzione a un problema simile. Avevo già deciso di utilizzare memcached per l'archiviazione di sessioni su Linux (con connect-memcached), ma ho anche richiesto la possibilità di eseguire su Windows. Ho passato un po 'di tempo a cercare una memoria di archiviazione in memoria per un'app di nodo a processo singolo. Redis e Memcached non sembrano essere ben supportati su Windows e non volevo la complessità aggiuntiva della loro installazione.

Ho trovato session-memory-store in un altro thread Overflow dello stack, che sembra buono ma ha aumentato significativamente le dimensioni delle mie dipendenze.

Infine, ho trovato memorystorenella documentazione per express-session. Avevo perso in origine a causa del simile del suo nome al default MemoryStore, ma è esattamente quello che stavo cercando:

espresso sessione completa funzionalità del modulo MemoryStore senza perdite!

Attualmente sto usando connect-memcached quando è in esecuzione in un cluster (solo su Linux) e memorystore quando si esegue un singolo processo (su Linux o Windows).

Ho pensato che valesse la pena postarla come un'altra risposta, nel caso in cui qualcun altro commetta l'errore di memoria mancante come inizialmente.

Problemi correlati