Java Driverのコネクションプールについて調べてみた
コネクションプールの設定について、ちょっと気になることがあったので調べてみた。
MongoDBのJava Driverで、コネクションプールのプール数に関連する設定として、以下のものがあります。
- connectionsPerHost
- The number of connections allowed per host (the pool size, per host)
- threadsAllowedToBlockForConnectionMultiplier
- multiplier for connectionsPerHost for # of threads that can block if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an exception will be throw
connectionsPerHostのHostってどこのこと?自分自身?接続先のmongod/mongos?わからなかったので動作確認してみた。
import java.util.ArrayList; import java.util.List; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.Mongo; import com.mongodb.MongoOptions; import com.mongodb.ServerAddress; import com.mongodb.WriteConcern; public class ConnectionTest { public static void main(String[] args) throws Exception { MongoOptions options = new MongoOptions(); options.connectionsPerHost = 3; options.threadsAllowedToBlockForConnectionMultiplier = 2; List<ServerAddress> addresses = new ArrayList<ServerAddress>(); addresses.add(new ServerAddress("localhost", 28101)); Mongo mongo = new Mongo(addresses, options); mongo.setWriteConcern(WriteConcern.SAFE); final DB db = mongo.getDB("hoge"); for(int i = 0;i < 9;i++){ Thread thread = new Thread(){ public void run() { long count = db.getCollection("user").count(); System.out.println(System.currentTimeMillis()); } }; thread.start(); } } }
結果は、ミリ秒が正しく表示された。9スレッドならOK。
1303230289466 1303230289470 1303230289477 1303230289476 1303230289474 1303230289473 1303230289472 1303230289488 1303230289494
次に、for文の数値を変更して10スレッド動作するように変更してみた。すると、以下のようにOut of semaphoresのエラーが表示されてしまった。
Exception in thread "Thread-3" com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db connection at com.mongodb.DBPortPool.get(DBPortPool.java:166) at com.mongodb.DBTCPConnector$MyPort.get(DBTCPConnector.java:325) at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:195) at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:295) at com.mongodb.DB.command(DB.java:152) at com.mongodb.DBCollection.getCount(DBCollection.java:760) at com.mongodb.DBCollection.getCount(DBCollection.java:731) at com.mongodb.DBCollection.count(DBCollection.java:686) at ConnectionTest$1.run(ConnectionTest.java:33) 1303230406895 1303230406898 1303230406904 1303230406903 1303230406902 1303230406901 1303230406900 1303230406912 1303230406915
この状態で、接続先のmongosをもう一つ追加して実行してみた。
addresses.add(new ServerAddress("localhost", 28101)); addresses.add(new ServerAddress("localhost", 28102));
結果は上記と同様にOut of Semaphoresのエラーが出力された。
以上より、MongoDBのJava Driverのコネクションプールは、以下のような仕組みらしい。
- connectionsPerHostの値だけコネクションが利用可能となる
- connectionsPerHost × threadsAllowedToBlockForConnectionMultiplierの値だけコネクションを待ち続けることが出来る
- connectionsPerHost + connectionsPerHost × threadsAllowedToBlockForConnectionMultiplierの値を超えるリクエストが来ると、以降のリクエストはOut of Semaphoreエラーが発生する
- 接続先のmongod/mongosの数は無関係。connectionsPerHostは、接続先ごとのコネクションプール数ではなく、あくまでアプリケーション内のプール数。
すっきりしたー。