- PR -

コネクションプーリングについて

投稿者投稿内容
ヨーヨー
会議室デビュー日: 2004/06/10
投稿数: 8
投稿日時: 2004-09-01 18:19
Struts + PostgreSQLでWEBアプリを開発してます。

DB接続部分で以下のようなソースで接続してます。

Class.forName(DB_DRIVER);
GenericObjectPool connectionPool = new GenericObjectPool(null);
DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(DB_URL, DB_USER, DB_PASSWD);
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, true, false);
PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
Connection conn = dataSource.getConnection();

この場合、GenericObjectPoolのコンストラクタで
アクティブなコネクションの最大数:8
コネクションが使い尽くされている場合の処理:1 = 待機
に設定されるはずですが、ApacheBenchで大量にリクエストを送信すると、
同時リクエスト数が1つずつの場合でもほとんどのリクエストで
PostgreSQLがエラーを返し、(FATAL: Sorry, too many clients already)
接続に失敗して終了してしまいます。

PostgreSQLのバージョンは7.3.4で、設定を変えた所といえば、
max_connections = 64、shared_buffers = 128
位です。

アクティブなコネクションの最大数を超える場合にちゃんと待機し、
DBに接続に行かないようにするには他に設定が必要なのでしょうか?
どなたかご教示願います。
tanabo
常連さん
会議室デビュー日: 2003/04/24
投稿数: 34
投稿日時: 2004-09-01 18:41
Strutsには暗いのですが・・・。

PostgreSQLでプーリングを行うなら、
---------------------------------------------
org.postgresql.jdbc2.optional.PoolingDataSource source =
new PoolingDataSource();
source.setDatabaseName(DBName);
source.setServerName(dbServerName);
source.setPortNumber(portNumber);
source.setUser(DBUser);
source.setPassword(DBPassword);
source.setMaxConnections(maxConnection);

Connection connection = source.getConnection();
--------------------------------

みたいな感じでいいと思います。
ヨーヨー
会議室デビュー日: 2004/06/10
投稿数: 8
投稿日時: 2004-09-01 19:46
tanabo様、返答ありがとうございます。

まずお詫びを。
ソースの部分はStrutsではなく、Jakarta CommonsのDBCPを使用したものでした。
失礼しました。

で、早速org.postgresql.jdbc2.optional.PoolingDataSourceを使用した
プーリングをsetMaxConnectionsを10で試させていただきましたが、
結果は同じで、ほとんどエラーで終了してしまいました。

他に原因があるのでしょうか?
どなたかご教示願います。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2004-09-01 20:56
プールに対してコネクションを返却していますか?
ヨーヨー
会議室デビュー日: 2004/06/10
投稿数: 8
投稿日時: 2004-09-01 21:02
かつのり様、返答ありがとうございます。

コネクションの返却は
conn.close()を呼ぶことにより可能とのことなので、
SQL処理終了後、この通りにしています。
ちょま吉
大ベテラン
会議室デビュー日: 2004/08/04
投稿数: 112
投稿日時: 2004-09-01 23:58
引用:

ヨーヨーさんの書き込み (2004-09-01 21:02) より:
かつのり様、返答ありがとうございます。

コネクションの返却は
conn.close()を呼ぶことにより可能とのことなので、
SQL処理終了後、この通りにしています。


conn.close()は、例外が起こっても必ず呼ばれるようになっていますか?
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-09-02 01:30
引用:

ヨーヨーさんの書き込み (2004-09-01 18:19) より:

DB接続部分で以下のようなソースで接続してます。



GenericObjectPoolを直接使ったことが無いのでよくわからないのですが、
リクエストの度に「コネクションプールを生成」してるんですか?

もしそうならあっという間に最大接続数に達して当然です。
そのそれぞれのプールはDB接続を抱えて離さないわけですから。
「コネクションプール」はアプリケーションインスタンス1つに対して1つだけで十分です。

設定ファイルを適切に記述すれば、
InitialContext ic = new InitialContext();
DataSource ds = (DataSource)ic.lookup("java:comp/env/jdbc/XXX"); //このDataSourceは適当にキャッシュする。
...
Connection conn = ds.getConnection(); //このConnectionはリクエストごとにget()/close()する。
try {
doSomething(conn);
} finally {
conn.close();
}

と、非常に簡単にコネクションプーリングを利用できるので、
難しいことをする前に、まずこれを試してみてはいかがでしょう?
サンプルはWebで探せば簡単に見つかるはずです。
taku
ぬし
会議室デビュー日: 2002/11/12
投稿数: 918
お住まい・勤務地: 墨田区→中野区
投稿日時: 2004-09-02 10:13
 PostgreSQLのJDBCドライバですが、
「org.postgresql.jdbc2.optional.PoolingDataSource」は 、
javax.sql.DataSourceの実装クラスです。
「org.postgresql.jdbc2.optional.ConnectionPool」は、
javax.sql.ConnectionPoolDataSourceの実装クラスです。
「javax.sql.DataSource」だと、
コネクションプーリングの実装は必須ではないので、
これで必ずしもコネクションプーリングを行えるとは限りません。
PostgreSQLの場合は、コネクションプーリングが、
有る実装クラスと無い実装クラスがあります。
上記のクラスはコネクションプーリング実装クラスですが、
コネクションプーリングを行うなら、
「javax.sql.ConnectionPoolDataSource」の実装クラスを使用するべきです。
何故なら、例え、コネクションプーリングを実装していても、
機能は劣っているからです。

 あと、J2SEは恐らくJ2SE1.4.xでしょうから、
「org.postgresql.jdbc3.Jdbc3PoolingDataSource」
「org.postgresql.jdbc3.Jdbc3ConnectionPool」
のどちらかを使用すべきです。

 下記はPostgreSQLのマニュアルを日本語に翻訳したものですが、
このあたりのことについて、全て記述されていますので、
下記をよく読んでください。
http://search.net-newbie.com/pgsql/jdbc-datasource.html#JDBC-DS-DS

スキルアップ/キャリアアップ(JOB@IT)