Что такое хорошее хранилище сеансов для узла с одним хостом.JS production app?
Я использую Node'S Express w / Connect middleware. Хранилище сеансов памяти 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.
для больших развертываний mongo или redis имеет смысл.
но что такое хорошее решение для приложения с одним хостом в производстве?
8 ответов:
провел день, изучая это. Вот варианты, которые я обнаружил. Запросы / секунда выполняются через
ab -n 100000 -c 1 http://127.0.0.1:9778/
на моей локальной машине.
- нет сеансов-быстро (438 req/sec)
- cookieSession: не требует внешнего обслуживания, незначительное влияние скорости (311 req / sec) - самый быстрый, сеансы истекают с файлом cookie (настроенным
maxAge
)- connect-redis: требуется сервер redis, большое влияние скорости (4 req / sec с redis2go и redisgreen) - быстрее, чем mongo, сеансы будут удалены через некоторое время (настроено
ttl
)- connect-mongo - требуется сервер mongodb, большое влияние скорости (2 req / sec с mongohq) - медленнее, чем redis, требует ручного
clear_interval
для установки в сеансы очисткивот coffeescript, который я использовал для cookieSession:
server.use express.cookieSession({ secret: appConfig.site.salt cookie: maxAge: 1000*60*60 })
вот coffeescript, который я использую для 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 })
вот мой coffeescript для монго:
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 будут медленнее, чем их локальные эквиваленты. я просто не мог заставить работать локальные эквиваленты, особенно учитывая, что время установки и обслуживания для меня было намного больше, чем я был готов инвестировать по сравнению с размещенными удаленными альтернативами, что-то, что я чувствую, верно и для других, поэтому почему эти размещенные удаленные службы баз данных существуют в первом место!
для локальной базы данных benhmarks см. @Мустафы.
рад за кого-то редактировать этот ответ чтобы добавить свои локальные тесты базы данных в микс.
поскольку принятый ответ связан только с удаленными хостами, очевидно, что он всегда будет медленнее, чем 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 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' }));
еще один хороший вариант-memcached. Состояния сеанса теряются, если memcached перезапускается, но практически никогда нет причин для этого. Вы можете оставить кэш работает все время, даже при перезагрузке сервера приложений. Доступ к данным сеанса практически мгновенный, и memcached будет работать счастливо с любым (соответствующим) объемом памяти, который вы ему даете. И я никогда не видел memcached crash (on Linux.)
https://github.com/elbart/node-memcache
вещи, чтобы иметь в виду о memcached вообще:
- никогда не иметь пробелов в ключи кэша
- имейте в виду, что существует максимальная длина ключа кэша, включая любой префикс пространства имен, который вы можете использовать. Если ваш ключ кэша слишком длинный, используйте вместо него односторонний хэш.
ни один из них не должен быть проблемой с хранением сеанса; просто с обобщенным кэширование.
Я пошел с магазином сеансов MongoDB, используя connect-mongo.
установить с
npm install connect-mongo
и заменить существующее хранилище памяти на
app.use(express.session({ store: new MongoStore({ db: 'some-database' }) }));
Он управляет стороной базы данных сеансов автоматически.
Я бы все равно использовал Redis даже для местного развития. Это полезно, потому что он сохраняет сеанс даже при перезапуске приложения узла, сохраняя сеанс браузера в системе. Redis по умолчанию сохраняет сеанс в памяти, так же как хранилище памяти connect просто настроить (я просто запускаю его на экране вместе с приложениями моего узла) может поддерживать несколько приложений, Если вы просто используете другую базу данных или значение сеанса в конфигурации.
Я просто исследую узел.js сам, но если вам не нужно хранить много информации в объекте сеанса-вы можете изучить безопасные куки.
безопасные файлы cookie хранят информацию о сеансе как часть файла cookie, который браузер хранит и пересылает с каждым запросом. Они зашифрованы, чтобы предотвратить подделку пользователем допустимого файла cookie.
преимущество в том, что вам не нужно поддерживать состояние на сервере-это решение хорошо масштабируется и просто осуществлять.
недостатком является то, что вы можете хранить до 4 КБ и данные отправляются на сервер по каждый запрос (но вы можете иметь несколько фиктивных доменов, указывающих на ваш сервер, чтобы вы не накладывали этот багаж на публично видимый статический контент, например).
поиск в интернете кажется, что есть по крайней мере две реализации безопасных куки для узла.js. Не уверен, насколько они готовы к производству, хотя:
https://github.com/benadida/node-client-sessions/blob/master/lib/client-sessions.js
проверьте мои тесты на https://github.com/llambda/express-session-benchmarks показаны сравнения различных реализаций сеанса.
Я понимаю, что это старый вопрос, но я наткнулся на него при поиске решения аналогичной проблемы. Я уже решил использовать memcached для хранения сеансов в Linux (с connect-memcached), но мне также требовалась возможность работать на Windows. Я потратил некоторое время, пытаясь найти хранилище сеансов в памяти для приложения с одним процессным узлом. Redis и Memcached, похоже, не очень хорошо поддерживаются в Windows, и я не хотел дополнительной сложности их установка.
нашел session-memory-store в другом потоке переполнения стека, который выглядит хорошо, но значительно увеличил размер моих зависимостей.
наконец, я нашел memorystoreв документации к экспресс-сеанс!--3-->. Я пропустил его первоначально из-за аналогичного его имени по умолчанию
MemoryStore
, но это именно то, что я искала:экспресс-сессии полнофункциональный модуль MemoryStore без утечек!
теперь я использую connect-memcached при запуске в кластере (только в Linux) и memorystore при запуске одного процесса (в Linux или Windows).
Я подумал, что стоит опубликовать это как еще один ответ, на всякий случай, если кто-то еще ошибется, пропустив memorystore, как я изначально сделал.