[WLS, Java, Database] Ensuring high level of performance with WebLogic JDBC

原文はこちら。
https://blogs.oracle.com/weblogicserver/ensuring-high-level-of-performance-with-weblogic-jdbc

原文はLaurent Goldsztejnによるものですが、Joseph Weinsteinが追加情報やコードサンプルを追加しています。
このエントリでは、WebLogic JDBCで高パフォーマンスを保証するためのベストプラクティスを紹介します。

Use WebLogic DataSources for connection pooling of JDBC connections

    実際にDBMS接続を作成するのは高コストで遅いので、データソースを使用して接続を保持し再利用するべきです。プールされた接続を使用する理想的なモードは、できるだけ迅速かつ短時間で使用し、必要なときにそれらを取得し、できるだけ早くそれらを閉じる(プールに戻す)ことです。これにより並行性が最大化されます。
    connection(接続)がメソッドレベルのオブジェクトであり、アプリケーションスレッド間で共有されず、アプリケーションコードの終了パスに関係なくクローズされることが重要です。そうしないと、プールから接続がリークし、すべての接続が取り出されて放棄されてしまいます。
    このエントリのベストプラクティスのコードサンプルを見てください。 WebLogic Datasourcesとアプリケーションやその他のWebLogic APIの長期的な強化と統合により、UCPやサードパーティのオプションに優先して選択できます。

    Use Oracle JDBC thin driver (Type 4) rather than OCI driver (Type 2)

      Oracle JDBC Thinドライバは、軽量(インストールと管理が容易)、プラットフォーム非依存(Javaで記述)、JDBC OCI(Oracle Call Interface)ドライバよりもわずかに高いパフォーマンスを提供します。Thinドライバは、クライアントサイドで追加ソフトウェアを必要としません。Oracle JDBCのFAQでは、Thinドライバのパフォーマンス上の利点が一貫していないこと、およびOCIドライバが一部のシナリオでより優れたパフォーマンスを提供できることも規定されています。WebLogicでOCIを使用すると、ネイティブ・ライブラリのバグによってWebLogic Server全体が停止する危険性があります。

      Use PreparedStatements objects rather than plain Statements 

        PreparedStatementsを使うと、コンパイル済SQLクエリプランはDBMSキャッシュに保持され、一度解析された後に再利用されます。

        Use/configure the WebLogic Datasource’s statement cache size wisely.

          データソースはキャッシュでき、プールされた接続から作成されたPrepared/CallableStatementを透過的に再利用できます。プールのステートメント・キャッシュサイズ(デフォルトは10)でその数を決定します。これはいくらかのメモリを必要としますが、たいていの場合、パフォーマンスが向上します。ただし、least recently usedポリシーではキャッシュサイズをパージするので、例えばデータソースを使用するアプリケーションが通常30個の個別のPreparedStatementを作成する場合、次回のリクエストごとに新しいステートメントがキャッシュに置かれ、以前利用された10個のステートメントは放り出されるため、ステートメントの再利用はできません。コンソールでは、いくつかのステートメントキャッシュ統計を使用して、すべてのステートメントを処理するようにキャッシュのサイズを設定できるようにしますが、メモリーが大きな問題になる場合は、キャッシュサイズをゼロに設定する方が良い場合があります。

          Close all JDBC resources ASAP, inline, and for safety, verify so in a finally block

            これには、LOBs、ResultSets、Statements、およびConnectionsオブジェクトが含まれ、メモリを最大限に活用しながら、特定のDBMSサイドのリソースの問題を回避します。仕様により、Connection.close()はそこからすべてのサブオブジェクトを閉じる必要があります。また、close()のWebLogicバージョンは実際の接続をプールに戻しながらクローズすることを意図していますが、一部のオブジェクトは、別のドライバで異なる実装になっている可能性があり、その実装ではWebLogicにすべてを解放させないかもしれません。LOBsなどのJDBCオブジェクトが正しく閉じられないと、以下のエラーが発生する可能性があります。
            java.sql.SQLException: ORA-01000: maximum open cursors exceeded.
            StatementとResultSetsを明示的に速やかに閉じないと、カーソルが蓄積され、接続を閉じる前にデータベースが許容する最大数を超えることがあります。

            以下はWebLogic JDBCのベストプラクティスのコード例です。
            (訳注)今ならtry-with-resourcesで書くでしょうし、例外を握りつぶしているのがなんともあれですが、原文のままにしています。

            public void myTopLevelJDBCMethod() {
                // メソッドレベルのオブジェクトとして定義され、他のスレッドが使用できる場所にはアクセスできない、もしくは保持されない。
                Connection c = null; 
            
                // JDBC利用にあたっての事前準備
            
                // このメソッド(およびサブメソッド)のすべてのJDBC操作が実行されるtryブロック
                try {
                  // WLSデータソースから直接接続を取得
                  c = myDatasource.getConnection();
            
                  // Connectionをサブメソッドに渡すことができるが、サブメソッドはConnectionを保持してはいけない。
                  // メソッドの終了後にConnectionがオープン/実行可能であることをオブジェクトまたはオブジェクトのいずれかから期待されている
                  doMyJDBCSubTaskWith( c );
            
                  // JDBC操作が終了したらすみやかに接続をクローズする
                  c.close(); 
            
                  //finallyブロックでConnectionが取得された場合でもクローズされたことがわかる
                  c = null; 
            
                  // JDBCを必要としないものは残しておいてもかまわない。
                  // JDBCとは関係ないデータの後処理を行う前にConnectionをできるだけ早く閉じると、
                  // 同時実行性が大きく向上する
                } catch (Exception e) {
            
                  // catchブロックが必要であればここに必要なロジックを記述する。
                  // ただし、finallyブロックは必ず配置しておく
            
                } finally {
                   // 接続を閉じずにここまで到達したら、finallyブロックの最初に以下を必ず実行する
                  If (c != null) try {c.close();} catch (Exception ignore){}
            
                  // finallyブロックに記述したいコード
                }
            }
            

            Set The Datasource Shrink frequency to 0 for fastest connection availability

            現在の負荷が不十分(想定よりも小さい)である場合、データソースの不要な部分(最小容量より大きい)を閉じて実際の接続数を変更するように設定でき、さらに、必要に応じて再作成されますが、これにより新しい置き換えの接続が作成されている間、負荷の上昇中にアプリケーションの速度が低下します。縮小率をゼロに設定することにより、データソースはすべての利用可能な接続を無期限に準備完了状態に保ちます。これは、あまりにも多くのアイドルセッションがある場合、DBMSのトレードオフになることがあります。

            Set the datasource test frequency to something infrequent or zero

            データソースは、アプリケーション負荷とは無関係に、現在使用されていない接続、プール内でアイドル状態の接続、不良な接続の置き換えなどを定期的にテストするように設定できます。これには、アクティブでない場合に接続を切断する可能性のあるファイアウォールやDBMSに対し、接続がビジー状態に見えるようにするなど、いくつかの利点があります。ただし、これはWLSのオーバーヘッドであり、必要に応じて予約時に接続をテスト(test connections on reserve)していれば、ほとんどの場合不要です。

            Consider skipping the SQL-query connection test on reserve sometimes

            予約時に接続をテストする機能は常にONにしておくべきです。というのも、DBMSの健全性に関するActive GridLinkの情報があっても、個々の接続が悪くなる可能性があるため、取得しようとしている接続が良好な状態であることを確実にする唯一の方法は、データソースを取得しようとしている直前にデータソーステストを行うことです。しかし、毎回この接続テストを実施するにはコストが高すぎる場合があります。具体的には短時間のユーザーユースケースに対して余計な時間が加わってしまうか、DBMSに負担がかかりすぎるためです。このような場合で、アプリケーションが時には不正な接続を取得することが多少許容される場合、データソースオプション「アイドル・プール接続を信頼する秒数」(デフォルトは10秒)があります。これは、信頼する秒数の間にプール内の接続が正常にテストされた場合、またはアプリケーションによって以前に正常に使用された場合、その接続を信頼し、それをテストせずにリクエスタに渡します。負荷が重く、回転が速い環境では、テストの明示的なオーバーヘッドを安全かつ完全に回避できます。

            Consider making the test as lightweight as possible

            データソースの 'Test Table'(テスト対象の表名)パラメータが設定されている場合、プールはそのテーブルから 'select * from'を実行して接続をテストします。DUALはOracle Databaseの場合における伝統的な選択です。JDBCのisValid()呼び出しを使用するオプションもあります。これはドライバによっては高速な場合があります。例えばOracle Databaseのdbping()の場合、実際にユーザーレベルのDBMS機能を呼び出さずにto-DBMSのネット接続をチェックします。高速ではあるものの、接続上は良好であったとしても、まれにユーザーセッション機能が壊れていることがあります。XA接続の場合、より大きなトレードオフです。テストテーブルへのクエリはそれ自身のXAトランザクション内で実行されますが、これはより大きなオーバーヘッドですが、次のユーザーXAトランザクションが失敗するようなセッションステートの問題を見つけ、回避して動作する上で有用なことがあります。

            Consider enabling Pinned-to-Thread

            デフォルトで無効になっています。このオプションは、特定のWLSスレッドにプール接続を透過的に割り当てることで、パフォーマンスを向上させることができます。これにより、データソースにアクセスする際にスレッド間の競合がなくなります。ただしpinned-to-thread(スレッドに固定)を有効にすると接続プールの最大容量が無視されるため、このパラメータは、細心の注意を払って使用する必要があります。各スレッド(おそらく数百)は独自のconnectionを必要とし、取得します。そのため、そのプールを縮小することはできません。

            Match the Maximum Thread Constraint property with the maximum capacity of database connections

            このプロパティ(コンソールのEnvironment Work Managerを参照)は、同時実行可能なアプリケーション・スレッド/実行の最大数を設定します。アプリケーションが並列実行できる場合、このWebLogicの制限以外に制限がない場合には、データソースの最大容量はこのスレッド数と一致する必要があります。したがって、他のスレッドから接続が返されるまで、アプリケーションスレッドは空のプールで待機する必要はありません。

            WebLogic Serverでシステムパフォーマンスを向上するためのJDBCデータ・ソースおよび接続プールでの追加のパラメータ・チューニングについては、以下のドキュメントをご覧ください。
            Oracle® Fusion Middleware Oracle WebLogic Server JDBCデータ・ソースの管理 12c (12.2.1.3.0)
            データ・ソース接続プールのチューニング
            https://docs.oracle.com/cd/E92951_01/wls/JDBCA/ds_tuning.htm
            Oracle® Fusion Middleware Administering JDBC Data Sources for Oracle WebLogic Server 12c (12.2.1.3.0)
            Tuning Data Source Connection Pools
            https://docs.oracle.com/middleware/12213/wls/JDBCA/ds_tuning.htm
            アプリケーション固有の設計や構成については以下のドキュメントをご覧ください。
            Oracle® Fusion Middleware Oracle WebLogic Server JDBCアプリケーションの開発 12c (12.2.1.3.0)
            JDBCアプリケーションのパフォーマンス・チューニング
            https://docs.oracle.com/cd/E92951_01/wls/JDBCP/performance.htm
            Oracle® Fusion Middleware Developing JDBC Applications for Oracle WebLogic Server 12c (12.2.1.3.0)
            Performance Tuning Your JDBC Application
            https://docs.oracle.com/middleware/12213/wls/JDBCP/performance.htm

            0 件のコメント:

            コメントを投稿