Skip to content

コネクションポーリングとキャッシュ

前回のチュートリアルでは、Exposedフレームワークを使用してWebサイトに永続性を追加しました。 このチュートリアルでは、HikariCPとEhcacheライブラリをそれぞれ使用して、データベースのコネクションポーリングとキャッシュを実装する方法を見ていきます。

依存関係の追加

まず、HikariCPとEhcacheライブラリの依存関係を追加する必要があります。 gradle.propertiesファイルを開き、ライブラリのバージョンを指定します:

kotlin
h2_version = 2.3.232
hikaricp_version = 5.1.0

次に、build.gradle.ktsを開き、以下の依存関係を追加します:

kotlin

build.gradle.ktsファイルの右上にある Load Gradle Changes アイコンをクリックして、新しく追加された依存関係をインストールします。

コネクションポーリング

Exposedは、transactionコールのスコープ内でデータベースの最初の操作を実行する際に、各transaction呼び出しの内部で新しいJDBCコネクションを開始します。 しかし、複数のJDBCコネクションを確立するのはリソースの消費が激しいため、既存のコネクションを再利用することでパフォーマンスを向上させることができます。 コネクションポーリング(connection pooling)の仕組みがこの問題を解決します。

このセクションでは、HikariCPフレームワークを使用して、アプリケーションでのJDBCコネクションポーリングを管理します。

接続設定を設定ファイルに抽出する

前回のチュートリアルでは、com/example/dao/DatabaseSingleton.ktファイル内でdriverClassNamejdbcURLをハードコードしてデータベース接続を確立しました:

kotlin

データベース接続設定をカスタム設定グループに抽出しましょう。

  1. src/main/resources/application.confファイルを開き、ktorグループの外側に以下のようにstorageグループを追加します:

    kotlin
  2. com/example/dao/DatabaseSingleton.ktを開き、設定ファイルからストレージ設定をロードするようにinit関数を更新します:

    kotlin

    これで、init関数はApplicationConfigを受け取り、config.propertyを使用してカスタム設定をロードするようになります。

  3. 最後に、com/example/Application.ktを開き、アプリケーションの起動時に接続設定をロードするために、environment.configDatabaseSingleton.initに渡します:

    kotlin

コネクションポーリングを有効にする

Exposedでコネクションポーリングを有効にするには、Database.connect関数のパラメータとしてDataSourceを渡す必要があります。 HikariCPは、DataSourceインターフェースを実装するHikariDataSourceクラスを提供しています。

  1. HikariDataSourceを作成するために、com/example/dao/DatabaseSingleton.ktを開き、DatabaseSingletonオブジェクトにcreateHikariDataSource関数を追加します:

    kotlin

    データソース設定に関する注意事項は以下の通りです:

    • createHikariDataSource関数は、ドライバーのクラス名とデータベースURLをパラメータとして受け取ります。
    • maximumPoolSizeプロパティは、コネクションプールが到達できる最大サイズを指定します。
    • isAutoCommittransactionIsolationは、Exposedで使用されるデフォルト設定と同期するように設定されています。
  2. HikariDataSourceを使用するには、それをDatabase.connect関数に渡します:

    kotlin

    これでアプリケーションを実行し、すべてが以前と同じように動作することを確認できます。

キャッシュ

データベースにデータベースキャッシュを補完することができます。 キャッシュは、頻繁に使用されるデータを一時メモリに保存できるようにする手法であり、データベースの負荷を軽減し、頻繁に必要とされるデータの読み取り時間を短縮できます。

このチュートリアルでは、Ehcacheライブラリを使用してファイル内にキャッシュを構成します。

キャッシュファイルのパスを設定に追加する

src/main/resources/application.confファイルを開き、storageグループにehcacheFilePathプロパティを追加します:

kotlin

このプロパティは、キャッシュデータの保存に使用されるファイルへのパスを指定します。 後で、キャッシュを操作するためのDAOFacade実装を設定するためにこれを使用します。

キャッシュの実装

キャッシュを実装するには、キャッシュから値を返し、キャッシュされた値がない場合はデータベースインターフェースに委譲する別のDAOFacade実装を提供する必要があります。

  1. com.example.daoパッケージに新しいDAOFacadeCacheImpl.ktファイルを作成し、以下の実装を追加します:

    kotlin

    このコードサンプルの簡単な概要:

    • キャッシュの初期化と設定を行うために、EhcacheのCacheManagerインスタンスを定義します。ディスクストレージに使用するルートディレクトリとしてstoragePathを指定します。
    • 記事をIDごとに保存するエントリ用のキャッシュを作成します。articlesCacheInt型のキーをArticle型の値にマップします。
    • 次に、ローカルメモリとディスクリソースのサイズ制約を指定します。これらのパラメータの詳細については、Ehcacheのドキュメントを参照してください。
    • 最後に、指定された名前、キー、値の型を使用してcacheManager.getCache()を呼び出すことで、作成されたキャッシュを取得します。
  2. キャッシュで使用するために、Articleクラスはシリアライズ可能であり、java.io.Serializableを実装している必要があります。 com/example/models/Article.ktを開き、次のようにコードを更新します:

    kotlin
  3. これでDAOFacadeのメンバーを実装する準備が整いました。 DAOFacadeCacheImpl.ktに戻り、次のメソッドを追加します:

    kotlin
    • allArticles: すべての記事をキャッシュしようとはせず、これをメインデータベースに委譲します。
    • article: 記事を取得する際、まずキャッシュに存在するかどうかを確認し、存在しない場合にのみ、メインのDAOFacadeに委譲し、その記事をキャッシュにも追加します。
    • addNewArticle: 新しい記事を追加する際、メインのDAOFacadeに委譲しますが、その記事をキャッシュにも追加します。
    • editArticle: 既存の記事を編集する際、キャッシュとデータベースの両方を更新します。
    • deleteArticle: 削除時には、キャッシュとメインデータベースの両方から記事を削除する必要があります。

DAOFacadeCacheImpl の初期化

DAOFacadeCacheImplのインスタンスを作成し、アプリケーションが起動する前にデータベースに挿入されるサンプル記事を追加しましょう:

  1. まず、DAOFacadeImpl.ktファイルを開き、ファイルの下部にあるdao変数の初期化を削除します。

  2. 次に、com/example/plugins/Routing.ktを開き、configureRoutingブロック内でdao変数を初期化します:

    kotlin

    以上です。 これでアプリケーションを実行し、すべてが以前と同じように動作することを確認できます。

コネクションポーリングとキャッシュを含む完全な例は、こちらで見つけることができます:tutorial-website-interactive-persistence-advanced