Usando MemoryStore na produção


116

Hoje executei meu aplicativo Node.js no modo "produção" pela primeira vez e recebi este aviso:

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

Só preciso executar um único processo, mas o que devo usar no lugar? Quero que minhas sessões residam na RAM para acesso rápido. Também quero ser capaz de descartar todas as sessões simplesmente fechando o aplicativo Node.

Parece um exagero instalar Redis, MongoDB ou outro banco de dados apenas para essa tarefa simples. Eu também não entendo por que o MemoryStore está incluído no Node quando ele realmente não deveria ser usado?

Respostas:


29

MemoryStore é apenas para o modo de desenvolvimento (rápido), pois se seu aplicativo reiniciar (o processo morre) você perderá todos os dados da sessão (que residiam na memória desse processo).

Se você não quiser usar um banco de dados, use o armazenamento criptografado de cookies.

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


80

Ok, depois de falar com os desenvolvedores do Connect, consegui mais informações. Existem duas coisas consideradas vazamentos de memória aqui:

  1. problema com a análise JSON, que já foi corrigido nas versões recentes
  2. o fato de que não há limpeza de sessões expiradas se os usuários nunca as acessarem (ou seja, a única limpeza é ao acessar)

A solução parece ser bastante simples, pelo menos é o que pretendo fazer: usar setInterval para limpar periodicamente as sessões expiradas. MemoryStore fornece all () para obter a lista e podemos usar get () para forçar a leitura e, assim, expirá-la. Pseudo-código:

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

Agora, basta chamar sessionCleanup periodicamente via setInterval () e você terá a coleta de lixo automática para sessões expiradas. Não há mais vazamentos de memória.


3
Descobri que você também pode usar Redis e Mongo como armazenamento de apoio e fazer com que o banco de dados o limpe. No caso do Mongo, você pode definir a data de validade enquanto garante a indexação.
abraço de

57
É realmente uma coisa estúpida que eles fizeram ao colocar esta mensagem lá. É como "poderíamos ter acertado, mas, em vez disso, vamos errar e você vai jogar um jogo de adivinhação na internet. Ha ha! Perdedores!"
catanfetamina

2
qual é o valor de var sessionStore?
Dimitri Kopriwa

4
sessionStore? Isso é uma variável global node.js? Se não, como posso obter uma referência ao armazenamento da sessão em node.js?
windchime

1
@MilanBabuskov - você coloca isso em seu app.jsarquivo? Existe uma opção para emitir um retorno de chamada dentro da sessão expressa? Um pouco mais de detalhes sobre como implementar isso seria ótimo.
Jonathan Bechtel

46

Portanto, a resposta aceita para isso é [edit: was] praticamente um hack, e os outros estão apenas recomendando o uso de um banco de dados, o que eu acho um exagero.

Eu tive o mesmo problema e apenas substituí express-session por cookie-session .

Para fazer isso, basta instalar cookie-session:

npm install cookie-session

Em seguida app.js, encontre onde express-sessionestá sendo usado e substitua por cookie-session.

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

Você pode precisar mudar algumas outras coisas, para mim foi uma simples troca-fora-bobs-seu-tio-não-prejudicado.


2
como você fez isso.
Sid

2
Esta é realmente uma resposta útil. Obrigado.
smonff 01 de

5
a diferença é que cookie-sessionarmazena os dados no cliente, enquanto express-sessionarmazena os dados no servidor.
George,

11

Este módulo foi projetado para lidar com o problema de vazamento de memória. https://www.npmjs.com/package/session-memory-store

A resposta aceita pode ser boa. No entanto, como essa pergunta aparece no topo da lista de resultados da pesquisa, decidi incluir isso, caso ajude mais alguém.


Ainda não tentei isso, mas parece uma ótima solução para a situação (se o OP estiver ok com sessões perdidas na reinicialização do aplicativo)
stujo

Do seu link: "Não é altamente recomendável usá-lo em produção!". A questão é sobre "Usando o MemoryStore na produção".
Damien

Certo, mas apenas porque "você não pode compartilhar a sessão com outros processos ou outro serviço." Ou seja, existem outras soluções mais práticas por aí. Mas isso resolve o problema de vazamento de memória, portanto, se essas não forem preocupações para você, não há problema em usar e aborda a preocupação na questão.
Dovev Hefetz

7

Acho que o consenso em torno da web é que a maneira certa seria usar um banco de dados para isso, mas se você tiver certeza de que não quer fazer isso, suprima o aviso - o aviso não é lei.

No entanto, como você e eu concordamos que o vazamento de memória é um problema real, é difícil justificar dizer que redis é um exagero, pois isso resolveria o seu problema.

Eu também não entendo por que o MemoryStore está incluído no Node quando ele realmente não deveria ser usado

esse é um ponto importante - mas, quanto a isso, eu diria que o node iself só recentemente ficou pronto para a produção . Algumas pessoas não concordariam com a noção de que é.


2
Suprimir o aviso não fará com que o vazamento de memória desapareça.
Milan Babuškov

lol é por isso que eles desaconselham você usá-lo na produção. então a alternativa é usar um método alternativo de armazenamento, não é?
Kristian

1
Acho que simplesmente não gosto das alternativas que encontrei até agora. Estou procurando uma alternativa simples de javascript na memória, não um sistema de banco de dados. Eu realmente não entendo por que eles não consertam. Quer dizer, quão difícil pode ser um simples Armazenamento de Memória ... Só espero que alguém já o tenha feito, para não ter que reinventar a roda.
Milan Babuškov

2
Eu sinto sua dor, mas o nó está muito sangrento agora .. meio que vem com o território
Kristian

7
MemoryStore não está incluído no Node, está incluído no Express / Connect
Mustafa

6

A alternativa é usar Redis ou Mongo como loja. Com o Mongo você usa o express-session-mongo módulo .

Há um conselho para remover sessões obsoletas com uma opção de indexação:

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

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

Como as sessões obsoletas são removidas pelo próprio banco de dados, a sessão Express não precisa lidar com a limpeza sozinha.

EDIT : Parece que você precisa ter seu próprio campo "lastAccess". Ao acessá-lo, você mesmo atualiza esse campo. Verifique a documentação do MongoDB expire-data http://docs.mongodb.org/manual/tutorial/expire-data/

EDIT2 :

Agora se torna db.sessions.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

O thread de segundo plano do Mongo para verificar esse campo é executado a cada 60 segundos. Portanto, o momento para remover o documento não é exato.


2

Para aqueles que estão tendo problemas com o Redis, tente o seguinte - espero que isso ajude.

Estou usando Redis para DEV e PROD e visando Express v4. No Windows, estou usando o conjunto de ferramentas leve MSOpenTech Redis v3.0, caso contrário, apenas uso o complemento Heroku Redis. Fazer funcionar via Node não foi muito difícil - até agora ...

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

Boa sorte!

ps. Acabei de reler a consulta original e percebi isso - desculpe!

Parece um exagero instalar Redis, MongoDB ou outro banco de dados apenas para essa tarefa simples.


0

Se você usa OSX, use

brew install memcached

se linux

apt install memcached

resolver a mensagem da sessão, porque o aplicativo pode se conectar ao serviço do memcache 127.0.0.1:11211.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.