LoginSignup
1
0

More than 1 year has passed since last update.

MongoDBのコネクションプールがわからなかったので調査

Last updated at Posted at 2023-02-14

恥ずかしながら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);
});

多分こんな感じですね。。。どこかのページでも似たような記述を見た気がしました、、、
変なことしてたらどなたかご指摘ください。。。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0