接続プーリング (バージョン 1.2.0-1.2.12 限定)

注意:

この節の内容は、1.3.0 以降のドライバには無関係です。 歴史的な情報として、かつてプーリングをどのように使っていたかを残しておきます。

最新版のドライバにはプーリングという概念がなく、プロセスごとに一つの接続を保持します。 接続形式 (ReplicaSet/standalone/mongos) と条件の組み合わせごとにプロセスがわかれます。

接続の作成は、ドライバが行う作業の中でも最も重量級の作業です。 接続を正しく確立するには、どんなに高速なネットワークであっても数百ミリ秒はかかることがあります。 そこで、ドライバが新たな接続を作る回数をできるだけ減らすために、 プールにある接続を再利用することを考えます。

ユーザーが新しい Mongo のインスタンスを作ると、 必要な接続はすべて接続プールから取り出します (レプリカセットへの接続には 複数の接続が必要となることもあります。それぞれが、セット内の個々のメンバーへの接続となります)。 Mongo のインスタンスがスコープ外に出ると、接続をプールに返します。 PHP のプロセスが終了すると、プール内のすべての接続が閉じられます。

"なぜこんなに接続をオープンしてしまっているの?"

接続プールが作成する接続の数が大量になることがあります。 これは意外なことではなく、ちょっとした計算をすればどれだけの接続が必要になるかがわかります。 接続の総数に影響するのは、次の三要素です。

  • connections_per_pool

    各接続プールが作成する接続の数は、デフォルトでは無制限です。 これは問題だと感じる人もいるでしょう。無制限に作れるとしても、 ファイルディスクリプタの制限があるから何千も作るのは無理じゃないか? と。 実際のところ、そこまで達することはあり得ません。 未使用の接続はプールに返されてその後再利用されるので、 後から接続を利用するときには新しく作るのではなく既存の接続を使います。 何千もの接続を一気に作ってどれもスコープから外れないようにでもしない限り、 接続の数は常識的な範囲に収まります。

    プール内の接続数を知るには MongoPool::info() を使います。 指定したサーバーの "in use" フィールドと "in pool" フィールドの値を足した結果が、 そのプールの接続の総数となります。

  • pools_per_process

    接続先の MongoDB サーバーごとに、自前の接続プールを持っています。 たとえばローカルのホスト名が "example.net" のときに "example.net:27017"、"localhost:27017"、そして "/tmp/mongodb-27017.sock" に接続すると、全部で 3 つの接続プールができることになります。 開いている接続プールの総数は MongoPool::info() で取得できます。

  • processes

    PHP のプロセスごとに、プール群は分かれています。 PHP-FPM や Apache は、一般的に 6 から数十の間の PHP ワーカープロセスを作ります。最大でどれだけの PHP プロセスが立ち上がる設定になっているか、確認しましょう。

    PHP-FPM を使っている場合は、接続数の見積もりは多少面倒です。 というのも、負荷が高くなると PHP-FPM ワーカーをより多く立ち上げるようになるからです。 安全側に倒すなら、max_children パラメータあるいは spare_servers+start_servers (のどちらか大きいほう) を確認しましょう。これが、想定すべき PHP プロセス数 (そして、プール数) となります。

これら 3 つの変数を掛け合わせた connections_per_pool * pools_per_process * processes で、接続の総数が得られます。connections_per_pool はプールによって異なることに注意しましょう。つまり、この計算をするときには connections_per_pool は最大値を使わなければなりません。

たとえば、プールごとに 30 の接続があって PHP のプロセスあたり 10 のプールを用意し、 さらに PHP が 128 プロセスあるものとします。この場合、マシン上での接続数は 38400 になります。したがって、これだけの数をさばける程度にファイルディスクリプタの制限を増やしておく必要があります。 ファイルディスクリプタの上限に達してしまうと、それ以上の接続は処理できなくなります。

接続プーリングに関する詳細な情報は MongoPool を参照ください。