Cassandra クライアントの使用
Apache Cassandra®は、フリーでオープンソースの分散型ワイドカラムストアのNoSQLデータベース管理システムで、多くのコモディティサーバーにまたがる大量のデータを処理するように設計されており、単一障害点のない高可用性を提供します。
このガイドでは、RESTサービスでCassandraデータベースを使用する方法を見ていきます。
このエクステンションはサードパーティによって開発されたもので、Quarkus Platformの一部です。 |
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.3
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
稼働中の Apache Cassandra、 DataStax Enterprise(DSE)、または DataStax Astraデータベース、あるいはきれいなDockerのインストール
アーキテクチャ
このクイックスタート・ガイドでは、 DataStax Javaドライバーを使用してApache Cassandra、DataStax Enterprise(DSE)、またはDataStax Astraデータベースに接続できる Cassandra Quarkusエクステンションを使用してRESTアプリケーションを構築する方法を説明します。
このガイドでは、DataStax Object Mapper も使用します。これは、Java から CQL にマッピングする強力なフレームワークで、CQLクエリーを手動で記述する手間を省くことで、アプリケーションのデータアクセス階層コードを大幅に簡素化します。
このガイドで構築されたアプリケーションは非常にシンプルです: ユーザーはフォームを使用してリストに要素を追加することができ、アイテムリストが更新されます。ブラウザーとサーバー間の情報はすべてJSONフォーマットで、各要素はCassandraデータベースに保存されます。
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。
ソリューションはCassandra QuarkusエクステンションGitHubレポジトリの クイックスタートディレクトリ にあります。
空白の Maven プロジェクトの作成
まず、新しいMavenプロジェクトを作成し、 quickstart
ディレクトリーに存在する pom.xml
ファイルをコピーします。
pom.xml
、必要なQuarkusのエクステンションや依存関係をすべてインポートしています。
データモデルとデータアクセスオブジェクトの作成
この例では、果物のリストを管理するアプリケーションを作成します。
まず、以下のように Fruit
クラスであらわされるデータモデルを作成してみましょう。
@Entity
@PropertyStrategy(mutable = false)
public class Fruit {
@PartitionKey
private final String name;
private final String description;
public Fruit(String name, String description) {
this.name = name;
this.description = description;
}
// getters, hashCode, equals, toString methods omitted for brevity
}
前述のとおり、ここではDataStax Object Mapperを使用しています。つまり、CQLクエリーを手動で記述するのではなく、データ・モデルにいくつかのアノテーションを付け、裏側でマッパーが適切なCQLクエリーを生成するのです。
これが、 Fruit
クラスが @Entity
でアノテーションされている理由です。このアノテーションは、Cassandraテーブルにマッピングされる エンティティ・クラス としてマークされます。このクラスのインスタンスは、Cassandraデータベースに自動的に永続化され、そこから取得されます。ここでは、テーブル名はクラス名から推測されます: fruit
。
また、name
フィールドは Cassandra パーティションキーを表すため、ObjectMapper ライブラリーの別のアノテーションである @PartitionKey
のアノテーションを付けています。
エンティティークラスには通常、今回のように @PropertyStrategy(mutable = false) のアノテーションが付けられている場合を除き、デフォルトの引数なしのコンストラクタが必要です。
|
次のステップでは、 Fruit
エンティティーのインスタンスを管理する DAO (データアクセスオブジェクト) インターフェイスを作成します。
@Dao
public interface FruitDao {
@Update
void update(Fruit fruit);
@Select
PagingIterable<Fruit> findAll();
}
このインターフェイスは、REST サービスで使用される操作を公開します。繰り返しになりますが、アノテーション @Dao
は DataStaxObjectMapper から取得され、このインターフェイスの実装も自動的に生成されます。
findAll
メソッドの特別なリターンタイプにも注意してください PagingIterable
: これはドライバーによって返される結果セットの基本タイプです。
最後に、 Mapper インタフェースを作成しましょう:
@Mapper
public interface FruitMapper {
@DaoFactory
FruitDao fruitDao();
}
@Mapper
アノテーションは、DataStax Object Mapperが認識する別のアノテーションです。マッパーはDAOインスタンスの構築を担当します。この場合、outマッパーは唯一のDAOである FruitDao
のインスタンスを構築します。
マッパー・インターフェースをDAO Beanのファクトリーと考えてください。もし、あなた自身のコードで特定のDAO Beanを構築し注入するつもりなら、まず、 @Mapper
インタフェースでそのための @DaoFactory
メソッドを追加する必要があります。
@DaoFactory メソッド名は関係ありません。
|
@DaoFactory
メソッドは、以下の型のBeanを返す必要があります:
-
@Dao
アノテーションの付与されたインタフェース。例:FruitDao
; -
@Dao
アノテーションの付与されたインタフェースのCompletationStage
。例:CompletionStage<FruitDao>
。 -
@Dao
アノテーションの付与されたインタフェースのUni
。例:Uni<FruitDao>
。
Uni は、Quarkusが使用しているリアクティブプログラミングライブラリであるMutinyライブラリの型です。これについては、後述の「リアクティブプログラミング」のセクションで詳しく説明します。
|
DAOとマッパーの実装の生成
もうお分かりだと思いますが、私たちは上記のインターフェイスを実装しません。代わりに、Object Mapperがそのような実装を生成してくれるのです。
Object Mapperは、2つのパーツから構成されています:
-
@Mapper
、@Dao
または@Entity
でアノテーションされたクラスについてクラスパスをスキャンし、それらのためのコードとCQLクエリを生成する(コンパイル時)アノテーション・プロセッサー、および -
生成されたクエリーを実行するためのロジックを含む実行時モジュール。
そのため、Object Mapperを有効にするには、2つのステップが必要です:
-
cassandra-quarkus-mapper-processor
アノテーション・プロセッサーを宣言します。Mavenでは、プロジェクトのpom.xml
ファイルのコンパイラ・プラグイン設定を以下のように変更することで実現出来ます:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>com.datastax.oss.quarkus</groupId>
<artifactId>cassandra-quarkus-mapper-processor</artifactId>
<version>${cassandra-quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Gradleでは、 build.gradle
ファイルに以下の行を追加することで実現します:
annotationProcessor "com.datastax.oss.quarkus:cassandra-quarkus-mapper-processor:${cassandra-quarkus.version}"
正しいアノテーション・プロセッサーを有効にしていることを確認してください!Cassandraドライバには、 java-driver-mapper-processor というObject Mapperアノテーション・プロセッサーが付属しています。しかし、Cassandra Quarkusエクステンションには、独自のアノテーション・プロセッサーも同梱されています: `cassandra-quarkus-mapper-processor `これは、ドライバーのものよりも多くの機能を備えています。このアノテーション・プロセッサーはQuarkusアプリケーションで使用するのに適した唯一のものなので、これが使用されているものであることを確認してください。また、両方のアノテーションプロセッサを一緒に使用しないでください。
|
-
プロジェクトの
pom.xml
ファイルのコンパイルスコープでjava-driver-mapper-runtime
の依存関係を以下のように宣言します:
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-runtime</artifactId>
</dependency>
このモジュールは "ランタイム "と呼ばれていますが、コンパイルスコープで宣言する必要があります。 |
プロジェクトが正しくセットアップされていれば、エラーなくコンパイルできるはずです。また、生成されたコードが target/generated-sources/annotations
ディレクトリに存在する筈です(Maven を使用している場合)。生成されたコードは、ほとんどがデータベースとやりとりするための内部処理なので、慣れる必要はないでしょう。
serviceとJSON RESTエンドポイントの作成
ここで、アプリケーションのビジネス層となる FruitService
を作成し、Cassandraデータベースから果物をセーブ/ロードします。
@ApplicationScoped
public class FruitService {
@Inject FruitDao dao;
public void save(Fruit fruit) {
dao.update(fruit);
}
public List<Fruit> getAll() {
return dao.findAll().all();
}
}
サービスが FruitDao
インスタンスを注入されていることに注意してください。このDAOインスタンスは、生成された実装のおかげで、自動的に注入されます。
Cassandra Quarkus エクステンションを使用すると、次の Bean のいずれかを独自のコンポーネントに挿入できます。
-
プロジェクト内にある
@Mapper
アノテーション付きインターフェイスすべて。 -
@Mapper
アノテーション付きインタフェースのCompletionStage
またはUni
を注入することもできます。 -
@DaoFactory
メソッドから返されるBean(とりうるBean型は上記を参照)。 -
QuarkusCqlSession
bean: このアプリケーションスコープのシングルトン Bean は、Cassandra クライアントへの主要なエントリーポイントです。これは、Quarkus 用に特別に調整されたメソッドを備えた特殊な Cassandra ドライバーセッションインスタンスです。javadoc をしっかり確認してください。 -
CompletationStage<QuarkusCqlSession>
やUni<QuarkusCqlSession>
を注入することも可能です。
この例では、 FruitMapper
と FruitDao
の両方をどこにでも注入できますが、 FruitService
に FruitDao
を注入しています。
最後に必要なのは、GETとPOSTのメソッドを公開するREST APIです。
@Path("/fruits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class FruitResource {
@Inject FruitService fruitService;
@GET
public List<FruitDto> getAll() {
return fruitService.getAll().stream().map(this::convertToDto).collect(Collectors.toList());
}
@POST
public void add(FruitDto fruit) {
fruitService.save(convertFromDto(fruit));
}
private FruitDto convertToDto(Fruit fruit) {
return new FruitDto(fruit.getName(), fruit.getDescription());
}
private Fruit convertFromDto(FruitDto fruitDto) {
return new Fruit(fruitDto.getName(), fruitDto.getDescription());
}
}
FruitResource
が FruitService
インスタンスを自動的に注入していることに注目してください。
通常、REST API とデータアクセス層の間で同じエンティティーオブジェクトを使用することはお勧めしません。各 API を互いに独立して進化させるには、これらのレイヤーを実際に分離し、個別の API を使用する必要があります。このように、異なるオブジェクトを ( FruitDto
) を使用する理由です。DTO という用語は、「Data Transfer Object」の略です。この DTO オブジェクトは、HTTP メッセージで JSON に対する変換を自動的に行います。
public class FruitDto {
private String name;
private String description;
public FruitDto() {}
public FruitDto(String name, String description) {
this.name = name;
this.description = description;
}
// getters and setters omitted for brevity
}
JSON との間の変換は、このガイドの pom.xml ファイルに含まれている Quarkus RESTEasy Reactive エクステンションによって自動的に行われます。アプリケーションに手動で追加する場合は、以下のスニペットをアプリケーションの ppm.xml ファイルに追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
JSONのシリアライゼーションレイヤーで使用されるDTOクラスは、デフォルトの引数なしのコンストラクタが必要です。 |
DTO から JSON への変換は自動的に処理されますが、それでも Fruit
から FruitDto
に、またはその逆に変換する必要があります。これは手動で行う必要があるので、 FruitResource
で 2 つの変換メソッド convertToDto
と convertFromDto
を宣言しています。
この例では、 Fruit と FruitDto は非常に似ているので、すべてに Fruit を使用しないのはなぜかと思うかもしれませんが、実際には、DTO とエンティティーの構造が大きく異なることは珍しくありません。
|
Cassandra データベースへの接続
ApacheCassandra または DataStaxEnterprise (DSE) への接続
構成する主なプロパティーは次のとおりです。Cassandraデータベースにアクセスするための contact-points
、ドライバーによって必要とされる local-datacenter
そしてオプションでバインド先のキースペースです。
設定のサンプルは以下のようになります。
quarkus.cassandra.contact-points={cassandra_ip}:9042
quarkus.cassandra.local-datacenter={dc_name}
quarkus.cassandra.keyspace={keyspace}
この例では、localhost上で動作する単一のインスタンスを使用しており、データを含むキースペースは k1
となっています。
quarkus.cassandra.contact-points=127.0.0.1:9042
quarkus.cassandra.local-datacenter=datacenter1
quarkus.cassandra.keyspace=k1
クラスタがプレーンテキスト認証を必要とする場合は、さらに2つの設定を行う必要があります。 username
と password
です。
quarkus.cassandra.auth.username=john
quarkus.cassandra.auth.password=s3cr3t
DataStaxAstra クラウドデータベースへの接続
DataStax Astra に接続する場合には、接続先とデータセンターを提供する代わりに、いわゆる セキュア接続バンドル を提供して、Astra のセキュア接続バンドルファイルへの有効なパスを指定する必要があります。セキュア接続バンドルは、AstraWeb コンソールからダウンロードできます。
Astra クラスターでは常に認証が必要なため、ユーザー名とパスワードも指定する必要があります。
DataStax Astraのサンプル構成は次のようになります。
quarkus.cassandra.cloud.secure-connect-bundle=/path/to/secure-connect-bundle.zip
quarkus.cassandra.auth.username=john
quarkus.cassandra.auth.password=s3cr3t
quarkus.cassandra.keyspace=k1
高度なドライバー設定
application.conf
または application.json
ファイルを使用して、他の Java ドライバーの設定を設定することができます。これらのファイルは、アプリケーションのクラスパスに配置する必要があります。すべての設定は、基礎となるドライバー設定メカニズムに自動的に渡されます。 application.properties
で quarkus.cassandra
のプレフィックスを付けて定義された設定は、 application.conf
または application.json
で定義された設定よりも優先されます。
設定の全リストを見るには、 ドライバーの設定リファレンス を参照してください。
ローカル Cassandra データベースの実行
デフォルトでは、Cassandra クライアントは、ポート 9042(デフォルトの Cassandra ポート)でローカル Cassandra データベースにアクセスするように構成されています。
設定 quarkus.cassandra.local-datacenter が、Cassandraクラスターのデータセンターと一致していることを確認してください。
|
ローカルのデータセンターの名前がわからない場合は、以下の CQL クエリを実行することでこの値を見つけることができます : SELECT data_center FROM system.local
|
Docker を使用して Cassandra データベースを実行する場合は、次のコマンドを使用してバックグラウンドでデータベースを起動できます。
docker run --name local-cassandra-instance -p 9042:9042 -d cassandra
次に、アプリケーションで使用するキースペースとテーブルを作成する必要があります。Dockerを使用している場合は、以下のコマンドを実行します。
docker exec -it local-cassandra-instance cqlsh -e "CREATE KEYSPACE IF NOT EXISTS k1 WITH replication = {'class':'SimpleStrategy', 'replication_factor':1}"
docker exec -it local-cassandra-instance cqlsh -e "CREATE TABLE IF NOT EXISTS k1.fruit(name text PRIMARY KEY, description text)"
CQLSH ユーティリティーを使用して、データベースに対話式に問い合わせることもできます。
docker exec -it local-cassandra-instance cqlsh
REST API のテスト
プロジェクトのルートディレクトリー:
-
mvn clean package
を実行してから、java -jar./target/cassandra-quarkus-quickstart-*-runner.jar
を実行してアプリケーションを起動します。 -
または、
mvn clean quarkus:dev
でアプリケーションを開発モードで実行します。
これで、curl コマンドを使用して、基盤となる REST API と対話できます。
fruit を作成するには以下を実行します。
curl --header "Content-Type: application/json" \
--request POST \
--data '{"name":"apple","description":"red and tasty"}' \
http://localhost:8080/fruits
Fruit を回収するには以下を実行します。
curl -X GET http://localhost:8080/fruits
フロントエンドの作成
それでは、 FruitResource
と対話するためのシンプルなウェブページを追加してみましょう。
Quarkus は、 META-INF/resources
ディレクトリーの下にある静的リソースを自動的に提供します。 src/main/resources/META-INF/resources
ディレクトリーに、このファイル の内容を含めて fruits.html
ファイルを追加します。
これで、REST サービスと対話できるようになりました。
-
まだの場合は、
mvn clean quarkus:dev
を使用してアプリケーションを起動します。 -
ブラウザーで
http://localhost:8080/fruits.html
を指定します。 -
フォームを使って新しいフルーツをリストに追加します。
Cassandra クライアントを使用したリアクティブプログラミング
QuarkusCqlSession
インタフェース を使用すると、Quarkus およびそのリアクティブフレームワークである Mutiny をシームレスに統合する一連のリアクティブメソッドにアクセスできます。
Mutinyに慣れていない方は、 Mutiny - 直感的なリアクティブプログラミングライブラリをご覧ください。 |
Mutiny でリアクティブプログラミングを使用してアプリケーションを書き換えてみましょう。
まず、リアクティブな方法で機能する別の DAO インターフェイスを宣言しましょう:
@Dao
public interface ReactiveFruitDao {
@Update
Uni<Void> updateAsync(Fruit fruit);
@Select
MutinyMappedReactiveResultSet<Fruit> findAll();
}
MutinyMappedReactiveResultSet
の使い方に注意してください。これは、ドライバが返すオリジナルの Publisher
から変換された特殊な Mutiny
型で、クエリの実行情報を取得するなど、いくつかの追加メソッドも公開されています。このインターフェイスで何も必要としない場合は、単純に Multi
を返すようにメソッドを宣言することもできます: Multi<Fruit> findAll()
、
同様に、メソッド updateAsync
は Uni
を返します。これは、ドライバーが返す元の結果セットから自動的に変換されます。
Cassandraドライバは、リアクティブコールにReactive Streamsの Publisher APIを使用しています。しかし、QuarkusフレームワークではMutinyを使用しています。そのため、 CqlQuarkusSession インターフェイスは、ドライバが返す Publisher インスタンスを透過的にリアクティブ型の Multi に変換します。 CqlQuarkusSession は Publisher を Uni に変換することもできます - この場合、パブリッシャーは最大で1行を出力し、その後完了することが期待されます。これは書き込みクエリ(行を返さない)や、最大で1行を返すことが 保証されている読み込みクエリ(例えばカウントクエリ)に適しています。
|
次に、 FruitMapper
を適応させて、 ReactiveFruitDao
インスタンスを構築する必要があります。
@Mapper
public interface FruitMapper {
// the existing method omitted
@DaoFactory
ReactiveFruitDao reactiveFruitDao();
}
これで、リアクティブ DAO を活用する ReactiveFruitService
を作成できます。
@ApplicationScoped
public class ReactiveFruitService {
@Inject ReactiveFruitDao fruitDao;
public Uni<Void> add(Fruit fruit) {
return fruitDao.update(fruit);
}
public Multi<Fruit> getAll() {
return fruitDao.findAll();
}
}
最後に、 ReactiveFruitResource
を作成できます。
@Path("/reactive-fruits")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ReactiveFruitResource {
@Inject ReactiveFruitService service;
@GET
public Multi<FruitDto> getAll() {
return service.getAll().map(this::convertToDto);
}
@POST
public Uni<Void> add(FruitDto fruitDto) {
return service.add(convertFromDto(fruitDto));
}
private FruitDto convertToDto(Fruit fruit) {
return new FruitDto(fruit.getName(), fruit.getDescription());
}
private Fruit convertFromDto(FruitDto fruitDto) {
return new Fruit(fruitDto.getName(), fruitDto.getDescription());
}
}
上記のリソースは、新しいエンドポイント reactive-fruits
を公開しています。その機能は、以前に FruitResource
で作成したものと同じですが、すべてがブロッキング操作なしでリアクティブな方法で処理されます。
上記の getAll () メソッドは Multi を返し、 add () メソッドは Uni を返します。これらのタイプは、以前使用した Mutiny タイプと同じで、Quarkus リアクティブ REST API により自動的に認識されるので、JSON に変換する必要はありません。
|
RESTEasy Reactive は、 Uni
や Multi
などの Mutiny リアクティブタイプをネイティブにサポートします。
この依存関係は、本書の pom.xml にすでに含まれていますが、新しいプロジェクトを最初から開始する場合は必ず追加するようにしてください。
リアクティブ REST API のテスト
上で説明したようにアプリケーションを開発モードで実行すると、curl コマンドを使用して基盤となる REST API と対話できます。
リアクティブ REST エンドポイントを使用して fruit を作成するには以下を実行します。
curl --header "Content-Type: application/json" \
--request POST \
--data '{"name":"banana","description":"yellow and sweet"}' \
http://localhost:8080/reactive-fruits
リアクティブ REST エンドポイントを使用して fruit を取得するには以下を実行します。
curl -X GET http://localhost:8080/reactive-fruits
リアクティブなフロントエンドの作成
次に、 ReactiveFruitResource
と対話するための簡単な Web ページを追加しましょう。 src/main/resources/META-INF/resources
ディレクトリーに、 このファイル の内容を含めて reactive-fruits.html
ファイルを追加します。
これで、リアクティブな REST サービスと対話できるようになりました。
-
まだの場合は、
mvn clean quarkus:dev
を使用してアプリケーションを起動します。 -
ブラウザーで
http://localhost:8080/reactive-fruits.html
を指定します。 -
フォームを使って新しいフルーツをリストに追加します。
ヘルスチェック
Quarkus SmallRye Health エクステンションを使用している場合には、Cassandra クライアントは、Cassandra クラスターへの接続を検証するための準備ヘルスチェックを自動的に追加します。このエクステンションは、本書の pom.xml にすでに含まれていますが、アプリケーションに手動で含める必要がある場合は、次を追加してください。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
ヘルスチェックが利用可能になると、アプリケーションの /health/ready
エンドポイントにアクセスして、接続検証ステータスに関する情報を取得できます。
mvn clean quarkus:dev
を使用して開発モードで実行している場合には、ブラウザーで http://localhost:8080/health/ready を指定すると、次のような出力が表示されます。
{
"status": "UP",
"checks": [
{
"name": "DataStax Apache Cassandra Driver health check",
"status": "UP",
"data": {
"cqlVersion": "3.4.4",
"releaseVersion": "3.11.7",
"clusterName": "Test Cluster",
"datacenter": "datacenter1",
"numberOfNodes": 1
}
}
]
}
アプリケーションでヘルスチェックをグローバルに有効にする必要があるが、Cassandra ヘルスチェックは有効にしない場合は、 application.properties で quarkus.cassandra.health.enabled プロパティーを false に設定して Cassandra ヘルスチェックを無効にできます。
|
メトリクス
Cassandra Quarkus クライアントは、Cassandra セッションおよび個々の Cassandra ノードに関するメトリクスを提供できます。このクライアントは、Micrometer と MicroProfile の両方をサポートします。
メトリクスの有効化の最初のステップは、使用する予定のメトリクスフレームワークに応じて、いくつかの依存関係を追加することです。
Micrometer でのメトリクスの有効化
Micrometer は、Quarkus アプリケーションで推奨されるメトリクスフレームワークです。
アプリケーションで Micrometer メトリクスを有効にするには、pom.xml に以下を追加する必要があります。
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-metrics-micrometer</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
このガイドでは Micrometer を使用しているため、上記の依存関係はこのガイドの pom.xml にすでに含まれています。
MicroProfile メトリクスを使用したメトリクスの有効化
pom.xml から Micrometer への依存関係を削除し、代わりに次の依存関係を追加します。
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-metrics-microprofile</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>
Cassandra メトリクスの有効化
アプリケーションでメトリクスが有効になっている場合でも、この機能をオプトインしない限り、Cassandra クライアントはメトリクスを報告しません。そのため、次のステップとして、 application.properties
ファイルで Cassandra メトリクスを有効化してください。
quarkus.cassandra.metrics.enabled=true
以上です!
最後の手順 (任意) で、Cassandra クライアントに追跡させる特定の Cassandra メトリクスをカスタマイズします。複数のメトリクスを追跡できますが、この手順をスキップすると、有用なメトリクスのデフォルトセットが自動的に追跡されます。
使用可能なメトリクス名の完全なリストについては、 Driver Setting Reference ページを参照してください。このページで advanced.metrics セクションを検索してください。また、Cassandra ドライバーのメトリクスについては、 ドライバーマニュアル で詳しく説明されています。
|
追跡するメトリクスをカスタマイズする場合は、次のプロパティーを使用する必要があります。
-
quarkus.cassandra.metrics.session.enabled
には、有効にするセッションレベルのメトリクス (セッションに対してグローバルなメトリクス) が含まれている必要があります。 -
quarkus.cassandra.metrics.node.enabled
には、有効にするノードレベルのメトリクス (Cassandra クライアントが接続する各ノードが独自のメトリクス値を取得するメトリクス) が含まれている必要があります 。
どちらのプロパティーにも、有効なメトリクス名をコンマ区切りにした一覧を使用できます。
たとえば、次の 3 つの Cassandra メトリクスを有効にする場合には、以下のとおりです。
-
セッションレベル:
session.connected-nodes
およびsession.bytes-sent
; -
ノードレベル:
node.pool.open-connections
。
次に、application.properties
に以下の設定を追加する必要があります。
quarkus.cassandra.metrics.enabled=true
quarkus.cassandra.metrics.session.enabled=connected-nodes,bytes-sent
quarkus.cassandra.metrics.node.enabled=pool.open-connections
本書の application.properties
ファイルでは、すでに多くのメトリクスが有効になっています。このメトリクスリストを開始点として使用して、アプリケーションの有用な Cassandra メトリクスを公開すると適切です。
メトリクスが適切に有効になっている場合には、有効になっているすべてのメトリクスのメトリクスレポートは、アプリケーションの /metrics
REST エンドポイントで利用できます。
mvn clean quarkus:dev
を使用して開発モードで実行している場合には、ブラウザーで http://localhost:8080/metrics
を指定するとメトリクスのリストが表示されます。名前に cassandra
が含まれているメトリクスを検索します。
Cassandra メトリクスを表示するには、Cassandra クライアントを初期化して接続する必要があります。遅延初期化 (以下を参照) を使用している場合には、アプリケーションが、実際に接続してデータベースに初めてアクセスするまで、Cassandra メトリクスは表示されません。 |
ネイティブモードでの実行
If you installed GraalVM, you can build a native image using:
mvn clean package -Dnative
ネイティブコンパイルにはかなりの時間がかかる可能性があることに注意してください。コンパイルが完了したら、次のようにネイティブ実行可能ファイルを実行できます。
./target/cassandra-quarkus-quickstart-*-runner
その後、ブラウザで http://localhost:8080/fruits.html
を開いてアプリケーションを使用します。
Eager初期化とLazy初期化の選択
上記のように、このエクステンションを使用すると、多くの種類の Bean を注入できます:
-
QuarkusCqlSession
やFruitDao
のようなシンプルなBean; -
そのBeanの非同期バージョン、例えば
CompletionStage<QuarkusCqlSession>
や `CompletionStage<FruitDao>> など; -
そのBeanのリアクティブバージョン、例えば
Uni<QuarkusCqlSession>
やUni<FruitDao>
など。
最も簡単な方法は、明らかにBeanを直接注入することです。これはほとんどのアプリケーションで問題なく動作するはずです。しかし、 QuarkusCqlSession
Beanとそれに依存するすべてのDAO Beanは、初めて使用できるようになる前に初期化するのに時間がかかるかもしれませんし、このプロセスはブロッキング操作です。
幸いにも、初期化のタイミングを制御できます。 quarkus.cassandra.init.eager-init
パラメーターは、 QuarkusCqlSession
bean を最初にアクセスしたタイミング (lazy) または、アプリケーションが起動するタイミング (eager) のいずれで初期化するべきかを判断します。このパラメーターのデフォルト値は、 false
で、init プロセスが遅延設定されていることを意味しています。たとえば、Cassandra データベースと対話する必要がある最初の REST 要求がある場合に、 QuarkusCqlSession
bean は、遅延して、最初にアクセスしたタイミングで初期化されます。
Using lazy initialization speeds up your application startup time, and avoids startup failures if the Cassandra database is not available. However, it could also prove dangerous if your code is fully non-blocking, for example if it uses reactive routes. Indeed, the lazy initialization could accidentally happen on a thread that is not allowed to block, such as a Vert.x event loop thread. Therefore, setting quarkus.cassandra.init.eager-init
to false
and injecting QuarkusCqlSession
should be avoided in these contexts.
Vert.x(または他のノンブロッキングフレームワーク)を使用し、遅延初期化動作を維持したい場合、代わりに目的のBeanの CompletionStage
または Uni
のみを注入する必要があります。これらのBeanを注入すると、初期化プロセスは遅延的にトリガーされますが、Vert.xのイベントループを活用したノンブロッキングの方法でバックグラウンドで発生します。こうすることで、Vert.xのスレッドをブロックするリスクを回避することができます。
quarkus.cassandra.init.eager-init
この場合、セッションBeanとすべてのDAO Beanは、アプリケーションの起動時にQuarkusのメインスレッドで、早期初期化されます。これにより、Vert.xスレッドをブロックする危険性がなくなりますが、その分、起動時間が長くなります。