恥ずかしながらMongoDBなどNoSQL系は業務経験がなく、最近勉強中の身です。
Express+Typescriptプロジェクトのひな形をささっと作るで作成したExpressからMongoDBに接続する形でやってます。
MongoDB公式のドライバを使用してますが、dbの接続部分は下記のような記述をよく見かけます。
MongoClient.connect('mongodb://localhost:27017/db', (err, db) => {
db.collection('mycollection').insertOne(xxxxxx);
db.close();
})
シンプルに、毎回connectしてcloseするの???コネクションプールとかないの???となったので実機で試してみた記事です。
なんとなく調べていると、MongoClientにプール数を指定することは可能で、connectメソッドを呼んでも毎回接続しているわけではなくプーリングされた接続を使いまわしているという情報を発見。
いろいろ実験してみます。
とりあえず試してみる
export async function connect() {
const client = await MongoClient.connect(MONGODB_URI, {
minPoolSize: 40, // コネクションプール数を40にしてみる
maxPoolSize: 40,
});
return client.db('example');
}
connect(); // 接続
結果
> db.serverStatus().connections
{
"current" : 42, // ローカルの接続もあるので多少ずれるけどOK
"available" : 777,
"totalCreated" : 304,
"active" : 2,
"exhaustIsMaster" : 0,
"exhaustHello" : 0,
"awaitingTopologyChanges" : 1
}
Expressを起動してconnectを呼ぶと、40のコネクションが作成されてますね。
connectを何度呼んでも最初に作成されたコネクションプールが使いまわされるのでしょうか?
なんとなく、最初に呼んだMongoClient.connectの戻り値(client)を使いまわすようにしないとだめな気がする。
試しに、40回connectを呼んでみる
export async function connect() {
const client = await MongoClient.connect(MONGODB_URI, {
minPoolSize: 40,
maxPoolSize: 40,
});
return client.db('example');
}
for (let i = 0; i < 40; i++) {
connect();
}
結果
> db.serverStatus().connections
{
"current" : 485, // 40余裕で超えてる!!
"available" : 334,
"totalCreated" : 8256,
"active" : 2,
"exhaustIsMaster" : 0,
"exhaustHello" : 0,
"awaitingTopologyChanges" : 1
}
ですよね。。。計算合わないけどとりあえずconnectを毎回呼んでよいものではなさそう。
というか、connectした結果をグローバル変数に突っ込んでおいて、Expressを起動 → あとみんなで共有。というやり方だろうな。きっと。
まとめ
export async function connect() {
const client = await MongoClient.connect(MONGODB_URI, {
minPoolSize: 40,
maxPoolSize: 40,
});
}
export let db: Db; // これをみんなで使いまわす
// connectに成功したらdbを変数に格納
// その後サーバを起動する
connect().then((d) => {
db = d;
server.listen(port);
});
多分こんな感じですね。。。どこかのページでも似たような記述を見た気がしました、、、
変なことしてたらどなたかご指摘ください。。。