NodeのExpress w/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.
大規模な展開では、mongoまたはredisが理にかなっています。
しかし、実稼働環境の単一ホストアプリに適したソリューションは何ですか?
これを見て一日を過ごした。ここに私が発見したオプションがあります。 1秒あたりの要求は、ローカルマシンのab -n 100000 -c 1 http://127.0.0.1:9778/
を介して実行されます。
maxAge
でカスタマイズ)ttl
でカスタマイズ)clear_interval
を設定する必要があるCookieSessionに使用したcoffeescriptは次のとおりです。
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
})
これがmongoの私の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データベースは、ローカルの同等のものよりも遅くなります。 ローカルの同等のものを機能させることができませんでした。特に、ホストされたリモートの選択肢と比較して、インストールとメンテナンスの時間は投資したいと思ったものよりもはるかに大きかったので、他の人にも当てはまるため、これらのホストされたリモートデータベースサービスが最初に存在する理由!
ローカルデータベースのベンチマークについては、 @ Mustafa's answer を参照してください。
誰かに喜んで この回答を編集 ミックスにローカルデータベースベンチマークを追加してください。
受け入れられた答えはリモートホストに接続するだけなので、ローカルホストよりも常に遅いことは明らかです。自宅の次のコンピューターであっても、そのコンピューターから読み取るのにミリ秒かかりますが、ローカルメモリはナノ秒しかかかりません。ローカルにインストールされたサーバーを使用してそれらを比較する必要があります。
ここに私のローカルPCからの結果があります:ご覧のとおり、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'
}));
別の良いオプションはmemcachedです。 memcachedを再起動するとセッション状態は失われますが、それを行う理由はほとんどありません。アプリサーバーを再起動した場合でも、キャッシュを常に実行したままにすることができます。セッションデータへのアクセスは事実上瞬時であり、memcachedは、与えられた(適切な)量のメモリで問題なく実行されます。そして、memcachedのクラッシュ(Linux上)は見たことがありません。
https://github.com/elbart/node-memcache
Memcachedに関する一般的な留意事項:
これらのどちらもセッションストレージの問題ではありません。一般化されたキャッシングのみ。
connect-mongo を使用してMongoDBセッションストアにアクセスしました。
_npm install connect-mongo
_でインストールし、既存のMemoryStoreを置き換えます
app.use(express.session({ store: new MongoStore({ db: 'some-database' }) }));
セッションのデータベース側を自動的に管理します。
ローカル開発にもRedisを使用します。これは、Nodeアプリケーションを再起動してもセッションを保存し、ブラウザーセッションのログインを維持します。Redisはデフォルトでセッションをメモリに保存します。 (ノードアプリと一緒に画面で実行するだけです)構成で異なるデータベースまたはセッション値を使用するだけであれば、複数のアプリケーションをサポートできます。
私は自分でnode.jsを調査していますが、セッションオブジェクトに多くの情報を保存する必要がない場合は、安全なCookieを調べることをお勧めします。
セキュアCookieは、ブラウザが各リクエストとともに保存および転送するCookieの一部としてセッション情報を保存します。ユーザーが有効なCookieを偽造できないように暗号化されています。
利点は、サーバーで状態を維持する必要がないことです。このソリューションは拡張性が高く、実装が簡単です。
欠点は、最大約4KBしか保存できず、データがeveryリクエストでサーバーに送信されることです(ただし、複数の架空のドメインを指すことができますたとえば、公開されている静的コンテンツにその荷物を押し付けないようにします)。
Webを検索すると、node.jsのセキュアCookieの実装が少なくとも2つあるようです。しかし、どのように生産準備が整っているのかわかりません:
https://github.com/benadida/node-client-sessions/blob/master/lib/client-sessions.js
これは古い質問であることに感謝しますが、同様の問題の解決策を探しているときに出くわしました。 Linuxのセッションストレージにmemcachedを使用することを既に決めていました( connect-memcached を使用)が、Windowsで実行する機能も必要でした。単一プロセスノードアプリのメモリ内セッションストレージを見つけようとしてしばらく費やしました。 RedisとMemcachedはWindowsでは十分にサポートされていないようで、インストールの複雑さをさらに増やしたくありません。
別のStack Overflowスレッドで session-memory-store を見つけました。これは見た目は良いですが、依存関係のサイズが大幅に増加しました。
最後に、 memorystoreexpress-sessionのドキュメントにありました。名前がデフォルトのMemoryStore
と似ているため、もともと見逃していましたが、まさに私が探していたものです。
リークのない高速セッションのフル機能のMemoryStoreモジュール!
現在、クラスターで実行する場合は(Linuxのみ)connect-memcachedを使用し、単一のプロセスを実行する場合は(LinuxまたはWindowsで)memorystoreを使用しています。
私が最初にやったように他の誰かがメモリストアを紛失するという間違いを犯した場合に備えて、これを別の答えとして投稿する価値があると思いました。
https://github.com/llambda/express-session-benchmarks でベンチマークを確認してください。異なるセッション実装の比較を示しています。