Что такое хорошее хранилище сеансов для производственного приложения Node.js с одним хостом? - PullRequest
67 голосов
/ 06 января 2012

Я использую промежуточное программное обеспечение Node's Express с Connect.Хранилище сеансов памяти Connect не подходит для производства:

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

Для более крупных развертываний имеет смысл использовать монго или redis.

Но что является хорошим решением для приложения с одним хостом в производстве?

Ответы [ 8 ]

83 голосов
/ 24 октября 2012

провел день, изучая это. Вот варианты, которые я обнаружил. Запросы в секунду выполняются через ab -n 100000 -c 1 http://127.0.0.1:9778/ на моей локальной машине.

  • нет сеансов - быстро (438 запросов / сек)
  • cookieSession : не требует внешнего сервиса, незначительное влияние на скорость (311 req / sec) - самое быстрое, сеансы истекают с cookie (настраивается maxAge)
  • connect-redis : требуется сервер redis, большое влияние на скорость (4 req / sec с redis2go и redisgreen) - быстрее, чем mongo, через некоторое время сеансы будут удалены (настраивается ttl)
  • connect-mongo - требуется сервер mongodb, большое влияние на скорость (2 требования / сек с mongohq) - медленнее, чем redis, для настройки сеансов очистки вручную требуется clear_interval

Вот код, который я использовал для cookieSession:

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

Вот код, который я использую для 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
})

Вот мой кофейный текст для монго:

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

Теперь, конечно, удаленные базы данных redis и mongo будут медленнее, чем их локальные эквиваленты. Я просто не мог заставить работать локальные эквиваленты, особенно учитывая, что время установки и обслуживания для меня было намного больше, чем я хотел инвестировать по сравнению с удаленными альтернативами, размещенными на хосте, что-то, что я считаю верным и для других, поэтому, почему эти размещенные службы удаленной базы данных существуют в первую очередь!

Относительно тестов локальной базы данных см. @ ответ Мустафы .

Рад, что кто-то отредактировал этот ответ , чтобы добавить свои тесты локальной базы данных в смесь.

69 голосов
/ 06 ноября 2013

Поскольку принятый ответ подключается только к удаленным хостам, очевидно, что он всегда будет медленнее, чем localhost. Даже если это следующий компьютер в вашем доме, считывание с этого компьютера займет миллисекунды, но локальная память занимает всего лишь наносекунды. Вы должны сравнить их, используя локально установленные серверы.

Вот мои результаты с моего локального компьютера: Видите ли, Redis почти так же быстро, как в оперативной памяти при высокой нагрузке. Вы можете клонировать мой репозиторий, чтобы эти тестовые коды были доступны: 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] 

Страницы, используемые в сессии - очень простые страницы;

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:

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

Конфигурация магазина Mongo:

app.use(express.cookieParser());
app.use(express.session({
    store: new MongoStore({
        url: 'mongodb://localhost/test-session'
    }),
    secret: 'hello'
}));
9 голосов
/ 06 января 2012

Другой хороший вариант - memcached.Состояния сеанса теряются, если memcached перезапускается, но практически нет никаких причин для этого.Вы можете оставить кеш запущенным все время, даже когда перезапускаете сервер приложений.Доступ к данным сеанса практически мгновенный, и memcached будет работать с любым (соответствующим) объемом памяти, который вы им предоставите.И я никогда не видел сбоев в memcached (в Linux).

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

Что нужно помнить о memcached в целом:

  • Никогда не иметь пробелов вваши ключи кеша
  • Имейте в виду, что существует максимальная длина ключа кеша, включая любой префикс пространства имен, который вы можете использовать.Если ваш ключ кеша слишком длинный, используйте вместо него односторонний хеш.

Ни один из них не должен быть проблемой с хранилищем сеанса;только с обобщенным кэшированием.

6 голосов
/ 06 января 2012

Я пошел в хранилище сеансов MongoDB, используя connect-mongo .

Установите с npm install connect-mongo и замените существующий MemoryStore на

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

Автоматически управляет стороной сеансов в базе данных.

5 голосов
/ 06 января 2012

Я бы все еще использовал Redis даже для локальной разработки. Это полезно, поскольку он сохраняет сеанс даже при перезапуске приложения Node, сохраняя сеанс браузера в системе. Redis по умолчанию сохраняет сеанс в памяти, так же как хранилище памяти connect легко настраивается (я просто запускаю его на экране вместе с Мои приложения узла) могут поддерживать несколько приложений, если вы просто используете другую базу данных или значение сеанса в конфигурации.

3 голосов
/ 06 января 2012

Я просто изучаю node.js, но если вам не нужно хранить много информации в объекте сеанса - возможно, вы захотите изучить безопасные куки.

Сеанс безопасного хранения кукиинформация как часть куки, которую браузер хранит и пересылает при каждом запросе.Они зашифрованы, чтобы предотвратить подделку пользователем действительного файла cookie.

Преимущество заключается в том, что вам не нужно поддерживать состояние на сервере - это решение хорошо масштабируется и его легко внедрить.

Недостатком является то, что вы можете хранить только до 4 КБ, и данные отправляются на сервер по каждому запросу (но вы можете иметь несколько фиктивных доменов, указывающих на ваш сервер, поэтому вы не навязываете этонапример, багажа в общедоступном статическом контенте).

При поиске в Интернете создается впечатление, что существует как минимум две реализации безопасных файлов cookie для node.js.Не уверен, насколько готово производство, хотя:

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

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

2 голосов
/ 23 февраля 2018

Я ценю, что это старый вопрос, но я наткнулся на него, когда искал решение похожей проблемы. Я уже решил использовать memcached для хранения сессий в Linux (с connect-memcached ), но мне также требовалась возможность работы в Windows. Я потратил некоторое время, пытаясь найти хранилище сеансов в памяти для приложения узла с одним процессом. Redis и Memcached не поддерживаются в Windows, и я не хотел дополнительной сложности их установки.

Я нашел session-memory-store в другом потоке переполнения стека, который выглядит хорошо, но значительно увеличил размер моих зависимостей.

Наконец, я нашел memorystore в документации для express-session . Изначально я пропустил его из-за того, что его имя аналогично названию по умолчанию MemoryStore, но это именно то, что я искал:

полнофункциональный модуль MemoryStore для экспресс-сессии без утечек!

Теперь я использую connect-memcached при работе в кластере (только в Linux) и memorystore при запуске одного процесса (в Linux или Windows).

Я подумал, что стоит опубликовать это как еще один ответ, на тот случай, если кто-то еще совершит ошибку, пропустив хранилище памяти, как я делал изначально.

1 голос
/ 02 декабря 2014

Проверьте мои тесты на https://github.com/llambda/express-session-benchmarks, показывающие сравнения различных реализаций сессий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...