コネクションポーリングとキャッシュ
前回のチュートリアルでは、Exposedフレームワークを使用してWebサイトに永続性を追加しました。 このチュートリアルでは、HikariCPとEhcacheライブラリをそれぞれ使用して、データベースのコネクションポーリングとキャッシュを実装する方法を見ていきます。
依存関係の追加
まず、HikariCPとEhcacheライブラリの依存関係を追加する必要があります。 gradle.propertiesファイルを開き、ライブラリのバージョンを指定します:
h2_version = 2.3.232
hikaricp_version = 5.1.0次に、build.gradle.ktsを開き、以下の依存関係を追加します:
build.gradle.ktsファイルの右上にある Load Gradle Changes アイコンをクリックして、新しく追加された依存関係をインストールします。
コネクションポーリング
Exposedは、transactionコールのスコープ内でデータベースの最初の操作を実行する際に、各transaction呼び出しの内部で新しいJDBCコネクションを開始します。 しかし、複数のJDBCコネクションを確立するのはリソースの消費が激しいため、既存のコネクションを再利用することでパフォーマンスを向上させることができます。 コネクションポーリング(connection pooling)の仕組みがこの問題を解決します。
このセクションでは、HikariCPフレームワークを使用して、アプリケーションでのJDBCコネクションポーリングを管理します。
接続設定を設定ファイルに抽出する
前回のチュートリアルでは、com/example/dao/DatabaseSingleton.ktファイル内でdriverClassNameとjdbcURLをハードコードしてデータベース接続を確立しました:
データベース接続設定をカスタム設定グループに抽出しましょう。
src/main/resources/application.confファイルを開き、ktorグループの外側に以下のようにstorageグループを追加します:kotlincom/example/dao/DatabaseSingleton.ktを開き、設定ファイルからストレージ設定をロードするようにinit関数を更新します:kotlinこれで、
init関数はApplicationConfigを受け取り、config.propertyを使用してカスタム設定をロードするようになります。最後に、
com/example/Application.ktを開き、アプリケーションの起動時に接続設定をロードするために、environment.configをDatabaseSingleton.initに渡します:kotlin
コネクションポーリングを有効にする
Exposedでコネクションポーリングを有効にするには、Database.connect関数のパラメータとしてDataSourceを渡す必要があります。 HikariCPは、DataSourceインターフェースを実装するHikariDataSourceクラスを提供しています。
HikariDataSourceを作成するために、com/example/dao/DatabaseSingleton.ktを開き、DatabaseSingletonオブジェクトにcreateHikariDataSource関数を追加します:kotlinデータソース設定に関する注意事項は以下の通りです:
createHikariDataSource関数は、ドライバーのクラス名とデータベースURLをパラメータとして受け取ります。maximumPoolSizeプロパティは、コネクションプールが到達できる最大サイズを指定します。isAutoCommitとtransactionIsolationは、Exposedで使用されるデフォルト設定と同期するように設定されています。
HikariDataSourceを使用するには、それをDatabase.connect関数に渡します:kotlinこれでアプリケーションを実行し、すべてが以前と同じように動作することを確認できます。
キャッシュ
データベースにデータベースキャッシュを補完することができます。 キャッシュは、頻繁に使用されるデータを一時メモリに保存できるようにする手法であり、データベースの負荷を軽減し、頻繁に必要とされるデータの読み取り時間を短縮できます。
このチュートリアルでは、Ehcacheライブラリを使用してファイル内にキャッシュを構成します。
キャッシュファイルのパスを設定に追加する
src/main/resources/application.confファイルを開き、storageグループにehcacheFilePathプロパティを追加します:
このプロパティは、キャッシュデータの保存に使用されるファイルへのパスを指定します。 後で、キャッシュを操作するためのDAOFacade実装を設定するためにこれを使用します。
キャッシュの実装
キャッシュを実装するには、キャッシュから値を返し、キャッシュされた値がない場合はデータベースインターフェースに委譲する別のDAOFacade実装を提供する必要があります。
com.example.daoパッケージに新しいDAOFacadeCacheImpl.ktファイルを作成し、以下の実装を追加します:kotlinこのコードサンプルの簡単な概要:
- キャッシュの初期化と設定を行うために、Ehcacheの
CacheManagerインスタンスを定義します。ディスクストレージに使用するルートディレクトリとしてstoragePathを指定します。 - 記事をIDごとに保存するエントリ用のキャッシュを作成します。
articlesCacheはInt型のキーをArticle型の値にマップします。 - 次に、ローカルメモリとディスクリソースのサイズ制約を指定します。これらのパラメータの詳細については、Ehcacheのドキュメントを参照してください。
- 最後に、指定された名前、キー、値の型を使用して
cacheManager.getCache()を呼び出すことで、作成されたキャッシュを取得します。
- キャッシュの初期化と設定を行うために、Ehcacheの
キャッシュで使用するために、
Articleクラスはシリアライズ可能であり、java.io.Serializableを実装している必要があります。com/example/models/Article.ktを開き、次のようにコードを更新します:kotlinこれで
DAOFacadeのメンバーを実装する準備が整いました。DAOFacadeCacheImpl.ktに戻り、次のメソッドを追加します:kotlinallArticles: すべての記事をキャッシュしようとはせず、これをメインデータベースに委譲します。article: 記事を取得する際、まずキャッシュに存在するかどうかを確認し、存在しない場合にのみ、メインのDAOFacadeに委譲し、その記事をキャッシュにも追加します。addNewArticle: 新しい記事を追加する際、メインのDAOFacadeに委譲しますが、その記事をキャッシュにも追加します。editArticle: 既存の記事を編集する際、キャッシュとデータベースの両方を更新します。deleteArticle: 削除時には、キャッシュとメインデータベースの両方から記事を削除する必要があります。
DAOFacadeCacheImpl の初期化
DAOFacadeCacheImplのインスタンスを作成し、アプリケーションが起動する前にデータベースに挿入されるサンプル記事を追加しましょう:
まず、
DAOFacadeImpl.ktファイルを開き、ファイルの下部にあるdao変数の初期化を削除します。次に、
com/example/plugins/Routing.ktを開き、configureRoutingブロック内でdao変数を初期化します:kotlin以上です。 これでアプリケーションを実行し、すべてが以前と同じように動作することを確認できます。
コネクションポーリングとキャッシュを含む完全な例は、こちらで見つけることができます:tutorial-website-interactive-persistence-advanced
