Payara Server 5における接続プールのご紹介
Originally published on 18 May 2021
Last updated on 26 May 2021
このブログ記事では、接続プールについて紹介し、ベスト・プラクティスを用いてPayara Serverで接続プールを設定する方法を紹介します。
(最終更新日 2021/04/06)
接続プールとは?
接続プールとは、データベースへの接続とその再利用(最も重要なことです)に使用できるデータベース接続のストアです。
接続プールの必要性
データベース接続は、作成するのにも維持するのにもコストがかかります。その理由は、以下のように様々です。
- データベースサーバーへのネットワーク接続の確立
- 接続文字列情報の解析
- ユーザー認証の実行
- データベースへの接続の初期化
- トランザクションのコンテクストの確立
一人のユーザーが使用するWebアプリケーションの場合、ユーザー・セッションの開始時にデータベース接続を作成し、終了時にデータベース接続を閉じることができます。しかし、これは非常に可能性の低いシナリオです。
さて、より現実的なシナリオとして、あなたのWebアプリケーションに何百人、何千人ものユーザーがアクセスすることを想像してみてください。各ユーザーのセッションでデータベースへの接続が行われると、まず接続が確立されるまでの間、ユーザーには遅延が生じ、次にシステム全体のパフォーマンスが低下します。
つまり、「なぜ必要なのか」という問いに対しては、「システムのパフォーマンスとスケーラビリティの両方を向上させるため」ということになります。
接続プールの働き
接続プールは、必要になるたび新しい接続を作成するのではなく、アプリケーション・サーバーの起動時に作成します。これらの接続は、使用したり再利用したりすることができます。新しい接続が必要になると、プールの中から利用可能な接続を探します。もし利用可能なものがあれば、リクエスターに返されます。利用可能な接続がない場合は、プール内の接続数やプールの構成に応じて、リクエストがキューイングされるか、新しい接続が確立されます。接続が終了すると、接続を閉じるのではなく、接続プールに戻され、次のリクエスターが使用できるようになります。
さて、これで理論的な話は終わりです。では、実際にはどのように機能するのでしょうか?
Payara Serverの接続プール
今回の実践的なデモンストレーションでは、以下のものを使用します。
- オペレーティング・システム- Ubuntu 18.04
- Javaバージョン - 1.8.0_172
- アプリケーション・サーバー – Payara Server 5.181
- データベース - H2
もし上記のいずれかの異なるバージョンを使用している場合には、結果が異なる可能性があります。
接続プールの作成 - 管理者コンソールから
まず、Payara Serverを起動します。これは、ターミナル・ウィンドウから以下のAsadmin CLIコマンドで行うことができます。
(ここでは、カレント・ディレクトリを /<payara-home>/bin とします)
./asadmin start-domain
サーバーが起動したら、 http://localhost:4848 から管理コンソールにアクセスできます。
左側のパネルで Resources → JDBC → JDBC Connection Pools を選択します。
New をクリックし、以下の値を入力します。
- Pool Name - test-pool
- Resource Type - sql.XADataSource
- Driver Vendor – H2
Next をクリックします。
今回の例では、H2を使ったインメモリ・データベース “test” を使用します。これは、次に表示される画面でずっと下にスクロールして、以下のプロパティを追加することで行います。
url => jdbc:h2:mem:test
その他のプロパティは、既定値のままで構いません。
(ここで表示されているプロパティは、使用されているDataSourceの実装、H2の場合はorg.h2.jdbcx.JdbcDataSourceから動的にスキャンされていることに注意してください。)
その他の既定値をすべて受け入れて、 “Finish” をクリックします。
接続テスト
- 接続プール名(test-pool)をクリックします。
- 画面上部の “Ping” ボタンをクリックします。
“Ping Succeeded” というメッセージが表示されるはずです。
接続プールの作成 - コマンドラインから
また、Asadmin CLI Toolを使って以下のように接続プールを作成することもできます。
./asadmin create-jdbc-connection-pool \
--datasourceclassname org.h2.jdbcx.JdbcDataSource \
--restype javax.sql.XADataSource \
--property url="jdbc\:h2\:mem\:test" test-pool2
ここでは、コロンをエスケープしなければならないことに注意してください。これは、エスケープされていないものが、複数のプロパティとその値を区切るために使用されるために必要です。例えば --property user=root:password=test:port=3306 です。また、コマンドラインで作成するプールとして “test-pool2” を使用していることに注意してください。
コマンドラインから接続をテストするには、次のAsadmin CLIコマンドを実行します。
./asadmin ping-connection-pool test-pool2
さて、接続プールの作成が完了したところで、接続プールの設定方法に関するいくつかのベストプラクティスを見てみましょう。
接続プールの作成 - アプリケーションごとのリソース
上記で作成した接続プールは、サーバーが管理するグローバル・プールです。これは、Payara Serverにデプロイされたすべてのアプリケーションに適用されることを意味します。Jakarta EEのアノテーションやデプロイメント記述子を用いて、アプリケーションごとに作成することもできます。ただし、Jakarta EEでは「データソース」 (“jdbc-resource”) が接続プールと同時に作成されるという違いがあります。
アノテーションを使用する場合は以下の通りです。
@DataSourceDefinition( name = "java:app/MyApp/MyDS", className = "org.h2.jdbcx.JdbcDataSource", url = "jdbc:h2:mem:test" )
web.xml、ejb-jar.xml、またはapplication.xml内のエントリを使用する場合は以下の通りです。
<data-source>
<name>java:app/MyApp/MyDS</name>
<class-name>org.h2.jdbcx.JdbcDataSource</class-name>
<url>jdbc:h2:mem:test</url>
</data-source>
接続プールのサイズ調整
接続プールは、最大の同時接続数に合わせてサイズを調整する必要があります。
最大サイズは、システムが処理できるクライアント・リクエストの最大数に合わせて設定してください。アプリケーションが100件のリクエストを受け取り、それぞれがデータベースへの接続を必要とする場合、接続プールが100未満では、これらのリクエストの一部は、接続が作成されるか利用可能になるまで待たなければなりません。
接続プールの最小サイズは、データベースへの接続が常に確立されるようにします。つまり、プールの最小サイズを10に設定し、10件のリクエストを受け取ったとすると、プールが新しい接続を作成するのを待つことなく、すべてのアプリケーションがデータベース接続を取得できるということです。
最小値ではシステムの負荷に関わらず接続を維持する必要があり、最大値では多数のデータベースの同時接続が必要になる可能性があるため、これらの値の設定には常にトレードオフの関係があります。
この値はお客様によって異なります。魔法のような数字はありませんので、お客様のアプリケーションを理解し、予想される負荷(定常時と最悪時の両方)を把握し、それが変化するかどうかを監視し、それに応じた値を設定する必要があります。一般的な経験則として、最大値を200から300へ、300から500へなど、常に増加させる必要がある場合は、ソフトウェア・アーキテクチャを見直す必要があるかもしれません。例えば、トランザクション処理システムでは、各トランザクションを個別にデータベースに保存しますが、複数のトランザクションを最初にキューに入れ、JDBCやJPAのバッチを使って一括してデータベースに保存するシステムに変更することができます。
最小/最大サイズの設定 - 管理者コンソールから
接続プール名をクリックし、 “Pool Settings”の下に “Initial and Minimum Pool Size” および “Maximum Pool Size” があります。これらを必要なサイズに設定します。
最小/最大サイズの設定 - コマンドラインから
プールの初期および最小サイズは以下のように設定します。
./asadmin set resources.jdbc-connection-pool.test-pool2.steady-pool-size=10
プールの最大サイズは以下のように設定します。
./asadmin set resources.jdbc-connection-pool.test-pool2.max-pool-size=200
最小/最大サイズの作成 - アプリケーションごとのリソース
アノテーションを使用する場合は以下の通りです。
@DataSourceDefinition( name = "java:app/MyApp/MyDS", className = "org.h2.jdbcx.JdbcDataSource", initialPoolSize = 10, minPoolSize = 10, maxPoolSize = 200, url = "jdbc:h2:mem:test" )
web.xml、ejb-jar.xml、またはapplication.xml内のエントリを使用する場合は以下の通りです。
<data-source> <name>java:app/MyApp/MyDS</name> <class-name>org.h2.jdbcx.JdbcDataSource</class-name> <initial-pool-size>10</initial-pool-size> <max-pool-size>200</max-pool-size>
<min-pool-size>10</min-pool-size> <url>jdbc:h2:mem:test</url> </data-source>
Payara Serverのsteady-pool-sizeプロパティは、ここでは2つの標準プロパティに変換されることに注意してください。一方、偶然にもmax-pool-sizeは標準記述子では全く同じ名前です。
接続の検証
接続の検証により、接続が古くなってからアプリケーションに接続が割り当てられることがないようにします。
接続の検証は、接続の有効性の保証と、検証によるパフォーマンスへの影響との間で、常にトレードオフの関係にあります。アプリケーションが無効な接続を返して、新しい接続を借りなければならなくなると、パフォーマンスに悪影響が出るので、適切なバランスを取ることが重要です。
プールからの接続を使用する前に、接続をテストするためのシンプルなクエリが送信されます。接続に問題がある場合は、プールから削除され、別のものが使用されます。ここでの問題は、データベースのダウンなどの問題が発生し、多数の接続がある場合、それらの接続はそれぞれテストされ、削除されるということです。
これを避けるために、接続の検証を設定し、接続に失敗した場合はすべての接続を閉じるようにすることができます。
接続の検証 - 管理者コンソールから
- プールの名前をクリックする
- Advancedタブを選択する
- スクロールダウンして “Connection Validation”を選択し、以下の設定を行う。
- Connection Validation - required
- Validation method - custom-validation
- Validation class name – org.glassfish.api.jdbc.validation.H2ConnectionValidation
同じ画面で、失敗時にすべての接続を閉じるかどうかも設定できます。
接続の検証 - コマンドラインから
接続の検証を有効にするには、以下のコマンドを実行します。
./asadmin set resources.jdbc-connection-pool.test-pool2.is-connection-validation-required=true
./asadmin set resources.jdbc-connection-pool.test-pool2.connection-validation-method=custom-validation
./asadmin set resources.jdbc-connection-pool.test-pool2.validation-classname=org.glassfish.api.jdbc.validation.H2ConnectionValidation
また、失敗時にすべての接続を閉じるかどうかは、以下のコマンドで設定できます。
./asadmin set resources.jdbc-connection-pool.test-pool2.fail-all-connections=true
接続の検証 - アプリケーションごとのリソース
アノテーションを使用する場合は以下の通りです。
@DataSourceDefinition( name = "java:app/MyApp/MyDS", className = "org.h2.jdbcx.JdbcDataSource", initialPoolSize = 10, minPoolSize = 10, maxPoolSize = 200, url = "jdbc:h2:mem:test", properties = { "fish.payara.is-connection-validation-required=true", "fish.payara.connection-validation-method=custom-validation", "fish.payara.validation-classname=org.glassfish.api.jdbc.validation.H2ConnectionValidation" }) )
web.xml、ejb-jar.xml、またはapplication.xml内のエントリを使用する場合は以下の通りです。
<data-source> <name>java:app/MyApp/MyDS</name> <class-name>org.h2.jdbcx.JdbcDataSource</class-name> <url>jdbc:h2:mem:test</url> <property> <name>fish.payara.is-connection-validation-required</name> <value>true</value> </property> <property> <name>fish.payara.connection-validation-method</name> <value>custom-validation</value> </property> <property> <name>fish.payara.validation-classname</name> <value>org.glassfish.api.jdbc.validation.H2ConnectionValidation</value> </property> <initial-pool-size>10</initial-pool-size>
<max-pool-size>200</max-pool-size>
<min-pool-size>10</min-pool-size>
</data-source>
なお、接続の検証に対応する標準的なプロパティはありません。Payara Serverでは、これらをベンダー固有のプロパティとして設定することができます。これらのプロパティは通常、主にデータソースのプロパティとして使用されます。Jakarta EE / common annotationsの仕様では、データソース用のプロパティと接続プール用のプロパティを明確に区別していません。Payara Serverでは、プール向けのプロパティの前に “fish.payara.” を付けることで、この区別をしています。
詳細は、Payara Platformドキュメント “Advanced Connection Pool Properties in Deployment Descriptors” を参照してください。
ステートメントおよび接続リークの検出
ステートメントおよび接続リークの検出では、タイムアウトを設定することにより、ステートメントや接続がアプリケーションによってクローズされていない場合に、それらをログに記録したりクローズしたりすることができます。
テストでは、リークを記録するだけで閉じられないように設定することをお勧めします。しかし、本番環境ではリークは閉じておくことをお勧めします。十分にテストしたのであれば何もないはずですが、もしあったとしても、それをそのままにしておくことはできません。モニタリング・ソフトウェアは、検出されたリークを警告するように設定されており、その後、さらなる調査を行い、修正を行うことができます。
既定では、これらの値は0に設定されており、検出はオフになっています。
ステートメントおよび接続リーク検出の設定 - 管理者コンソールから
- プールの名前をクリックする
- Advancedタブを選択する
- スクロールダウンして “Connection Settings” へ
- “Connection Leak Timeout” と “Statement Leak Timeout” の値を設定する
ステートメントおよび接続リーク検出の設定 - コマンドラインから
タイムアウトの値は、以下のコマンドで設定できます。
./asadmin set resources.jdbc-connection-pool.test-pool2.statement-leak-timeout-in-seconds=5
./asadmin set resources.jdbc-connection-pool.test-pool2.connection-leak-timeout-in-seconds=5
ステートメントおよび接続リーク検出の設定 - アプリケーションごとのリソース
アノテーションを使用する場合は以下の通りです。
@DataSourceDefinition( name = "java:app/MyApp/MyDS", className = "org.h2.jdbcx.JdbcDataSource", initialPoolSize = 10, minPoolSize = 10, maxPoolSize = 200, url = "jdbc:h2:mem:test", properties = { "fish.payara.is-connection-validation-required=true", "fish.payara.connection-validation-method=custom-validation", "fish.payara.validation-classname=org.glassfish.api.jdbc.validation.H2ConnectionValidation", "fish.payara.connection-leak-timeout-in-seconds=5", "fish.payara.statement-leak-timeout-in-seconds=5" }) )
web.xml、ejb-jar.xml、またはapplication.xml内のエントリを使用する場合は以下の通りです。
<data-source> <name>java:app/MyApp/MyDS</name> <class-name>org.h2.jdbcx.JdbcDataSource</class-name>
<url>jdbc:h2:mem:test</url> <property> <name>fish.payara.is-connection-validation-required</name> <value>true</value> </property> <property> <name>fish.payara.connection-validation-method</name> <value>custom-validation</value> </property> <property> <name>fish.payara.validation-classname</name> <value>org.glassfish.api.jdbc.validation.H2ConnectionValidation</value> </property> <property> <name>fish.payara.connection-leak-timeout-in-seconds</name> <value>5</value> </property> <property> <name>fish.payara.statement-leak-timeout-in-seconds</name> <value>5</value> </property>
<initial-pool-size>10</initial-pool-size>
<max-pool-size>200</max-pool-size>
<min-pool-size>10</min
-pool-size> </data-source>
これらの値が設定されると、接続やステートメントのリークが検出された場合、アプリケーション・ログに以下のようなメッセージが表示されます。
WARNING: A potential connection leak detected for connection pool test-pool. The stack trace of the thread is provided below:
WARNING: A potential connection leak detected for connection pool test-pool. The stack trace of the thread is provided below:
WARNING: A potential statement leak detected for connection pool test-pool. The stack trace of the thread is provided below:
At this point you can go back to your development team and get them to investigate the root cause.
結論
さて、今回のブログはここまでです。接続プールの概要、Payara Serverでの接続プールの作成・設定方法、ベスト・プラクティスの設定をご紹介しましたが、いかがでしたでしょうか。
すべてのサーバー設定に言えることですが、変更する前に必ずアプリケーションのニーズをよく見極める必要があります。特に本番環境で変更を加える前には、常にパフォーマンス・テストや負荷テストを行い、最適な設定を確認する必要があります。1つのサイズがすべてに合うわけではありません。最適な設定を決めたら、定期的にモニターして再評価し、常に最適な設定で動作するようにしてください。
Payara Platformの本番利用でヘルプは必要ですか?
Payara Enterpriseについて知ってください。
Related Posts
The Payara Monthly Catch - October 2024
Published on 30 Oct 2024
by Chiara Civardi
0 Comments
The Payara Monthly Catch - September 2024
Published on 30 Sep 2024
by Chiara Civardi
0 Comments