Что такое хорошее хранилище сеансов для узла с одним хостом.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 63

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/caolan/cookie-sessions

проверьте мои тесты на 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, как я изначально сделал.