The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

手助けの為のQuarkus Superheroes!

Duke

あなたはマイクロサービスを構築する開発者ですか?大きなシステムの一部である個々のマイクロサービスの開発とテストに苦労していますか?RESTベースのアプリケーションやイベントドリブンなアプリケーションの構築について学びたいと思いませんか?

はじめに

Quarkusには、開発者がQuarkusエコシステムのさまざまな機能に慣れるための優れた ドキュメントクイックスタートがあります。しかし、不足していたのは、これらの機能、パターン、ベストプラクティスを使用しながら、Quarkusが解決しようとしている問題を反映した、完全に実装された実世界のアプリケーションのサンプルセットでした。

この記事では、 Quarkus Superheroesのサンプルアプリケーションを紹介し、構築するための要件を説明し、ローカルで実行する方法や Kubernetesにデプロイする方法を説明します。また、このサンプルアプリケーションが紹介された Quarkus Insightsのエピソードもご覧いただけます。

要件

ただ面白いだけではなく、いくつかの条件が必要でした:

  • 全体のアーキテクチャは、マルチサービス・マイクロサービス・アーキテクチャであること。

  • RESTWebSocket、データベースとのやりとり、メッセージング、 ヘルスチェックモニタリング/メトリクスApache AvroOpenAPIの統合など、共通の機能をピックアップして、"hello world"以上ではあるが、"kitchen sink"ではないこと

  • アプリケーションは、Quarkusの各バージョンで最新の状態に保たれ、 標準的なQuarkusエコシステムの継続的インテグレーションの一部となり、 Quarkusのステータスダッシュボードに表示されることが望ましい

  • なるべくブロック型とリアクティブ型の両方の例があることが望ましい

  • システム全体としては

    • ローカルの開発者用マシンやKubernetes上で、ビルド、実行、デプロイ、デモが簡単にできること。

    • 独立したマイクロサービスのローカル開発を促進するために、Quarkusがどのように役立つかを紹介していること。

    • 簡素化のために 単一のGitHubリポジトリに含まれているが、マルチモジュールプロジェクト ではない こと。

  • システム内の各アプリケーションは

    • ローカルの開発者用マシンやKubernetes上で、ビルド、実行、デプロイ、デモが簡単にできること。

    • Javaバージョン11と17(JVMとネイティブの両方)の コンテナイメージを提供すること。

    • 完全に文書化されていること。

    • 完全に自動化された(文書化された)CI/CDプラクティスを持っていること。

    • ユニットテストと統合テストの完全なテストスイートを含んでいること。

初期リリース

Quarkus Superheroesアプリケーションの初期バージョンは、2022年2月初旬にリリースされました。いくつかのマイクロサービスが共存してより大きなシステムを形成しており、RESTを介して同期的に通信したり、 Apache Kafkaを介してイベントドリブンで通信したりしています。アプリケーションの中にはリアクティブなものもあれば、伝統的なものもあり、それぞれの種類の構築方法を紹介しています。

図1に示すWebベースのユーザーインターフェースで、スーパーヒーローがスーパーヴィランと戦うことができます。過去の戦いの結果もこのページに表示されます。

スーパー
Figure 1. スーパーヒーローのユーザーインターフェース

図2に示す追加のユーザーインターフェースでは、ヒーロー対ヴィランの勝率や上位10人の勝率とそれぞれの勝数など、過去の対戦統計が表示されます。

イベント
Figure 2. 対戦統計

ケープの裏側

図3は、本アプリケーションの全体的なアーキテクチャを示しています。

全体
Figure 3. 全体アーキテクチャ

4つのQuarkusアプリケーションがあり、それぞれについては後述しますが、 Angularアプリケーションと、いくつかのバックエンドサービスがあります。 PrometheusPostgreSQLApache KafkaApicurio Schema Registryの4つです。

ヒーロー・サービス

Heroサービスは、完全にリアクティブでノンブロッキングなHTTPマイクロサービスで、 Hero データモデルに対するCRUD操作を公開しています。REST層は、 RESTEasy Reactiveを使用してリアクティブなエンドポイントを実装しています。データは、 Quarkus Hibernate Reactive with Panacheリポジトリパターンを使用して PostgreSQLデータベースに永続化されます。さらに、Heroサービスは、 フィールドインジェクションよりもビーンの コンストラクタインジェクションを優先します。Heroサービスには、ユニットテストと統合テストの完全なスイートが含まれており、 モッキングスパイ隔離されたトランザクション内でのテストを使用しています。

起動時間を短縮するために、 利用可能な全ヒーロー3体の中から100体のランダムなヒーローだけがデータベースに読み込まれます。より多くのデータをロードしたい場合は、 レポの characterdata ブランチから all-heroes.sql を取得してください。そのデータを rest-heroes/src/main/resources/import.sqlと同様に rest-heroes/deploy/db-init/initialize-tables.sql にコピーしてください。

ヴィラン・サービス

Villainサービスは、 Villain データモデルに対するCRUD操作を公開するブロッキングHTTPマイクロサービスです。実際、 Villain データモデルは、 HeroサービスHero データモデルと同一です(テーブルの名前以外は)。また、Heroサービスと同じユースケースをすべて実装しています。唯一の違いは、Villainサービスがブロッキングであることと、 Quarkus Hibernate ORM with Panacheactive recordパターンを使用していることです。

REST層は、 RESTEasy Reactiveを使って、ブロック型のエンドポイントで実装されています。データは PostgreSQLデータベースに保存されます。Villainサービスはまた、いくつかのカスタム設定を作成して、どのように ConfigMappingオブジェクトを使うかを示すカスタム設定も作成します。さらに、Villainサービスは コンストラクタ・インジェクションよりもビーンの フィールド・インジェクションを好みます。Villainサービスはユニットテストと統合テストの完全なスイートを含み、 モッキングスパイ隔離されたトランザクション内でのテストを用います。

起動時間を短縮するために、 1体の悪役の中から100体のランダムな悪役だけをデータベースにロードしています。もっと多くのデータをロードしたい場合は、 レポの characterdata ブランチから all-villains.sql を取得してください。そのデータを rest-villains/src/main/resources/import.sqlにコピーし、さらに rest-villains/deploy/db-init/initialize-tables.sql.

ファイトサービス

Fightサービスは、完全にリアクティブでノンブロッキングなHTTPマイクロサービスで、ヒーローとヴィランの間で戦いを実行するためのRESTful APIを公開しています。REST層は RESTEasy Reactiveを使用して実装されており、リアクティブなエンドポイントを備えています。戦いのデータは、 Quarkus Hibernate Reactive with Panacheactive recordパターンを使用してPostgreSQLデータベースに永続化されます。また、Fightサービスでは、 フィールド・インジェクションよりも コンストラクタ・インジェクションを採用しています。

Fightサービスは、HeroサービスとVillainサービスの両方にREST呼び出しを行います。Heroサービスへの呼び出しは reactive rest clientを使用し、Villainサービスへの呼び出しは RESTEasy Reactive clientを使用します。RESTEasy Reactive clientは、 JAX-RSクライアントAPIMicroProfile Rest Client実装であり、そのコアはノンブロッキングです。すべての発信コールは、 リトライタイムアウトフォールバックサーキットブレーキングなどの レジリエンスパターンを使用しています。

さらに、Fightサービスは、 Apache Avro形式のファイトイベントをKafkaに エミットします。Fightスキーマは、 QuarkusのApicurio Avroエクステンションによって、 Apicurio Schema Registryに自動的に登録されます。

Fightサービスには、ユニットテストとインテグレーションテストの完全なスイートが含まれており、 モッキングスパイ隔離されたトランザクション内でのテストを使用しています。また、下流のRESTエンドポイントをモックするための Wiremockや、ユニット・テスト内でメッセージの検証を行うための インメモリKafkaコネクタを多用しています。また、 Dev Servicesの情報を注入して、 KafkaConsumer.NETなどのテスト・リソースを設定する方法も紹介しています。

イベント統計サービス

Event Statistics サービスは、 WebSocketHTTPレイヤーを公開するイベント駆動型のマイクロサービスです。 SmallRye Reactive Messagingを利用したKafkaトピック上で、 Apache Avroフォーマットの試合イベントをリッスンします。戦いのスキーマは、 Quarkus Apicurio Avro extensionによって Apicurio Schema Registryに自動的に登録されます。

統計情報は、上の図2に示すように、ブラウザベースのユーザーインターフェースで表示されます。チームの統計は、ヒーローとヴィランの勝利数の割合で表示されます。勝者の統計は、ヒーローとヴィランのそれぞれの勝利数で蓄積され、上位10人の勝利数が保持されます。統計情報は、WebSocketを介してUIにプッシュされます。

Event Statistics サービスには、 モッキングスパイを使用したユニット・テストと統合テストの完全なスイートが含まれています。また、 Dev Services の情報を注入して、 KafkaProducer のようなテスト・リソースを構成する方法も紹介しています。

スーパーヒーローUI

上の図1に示されているSuper Hero UIアプリケーションは、Node.jsを介してデプロイされた Angularシングルページアプリケーションです。このアプリケーションは、RESTを介してFightサービスと通信します。サンプルアプリケーションでは、Angular UIではなくQuarkusアプリケーションに焦点を当てています。

アプリケーションをローカルで実行する

アプリケーションをローカルで実行するには、目的に応じていくつかの方法があります。 Docker Composeは、 事前に構築されたコンテナイメージを使用して、 アプリケーション全体または そのサブセットを実行したい場合に使用できます。また、各アプリケーションを ソースから実行することもできます。

Docker Composeでローカルに実行

アプリケーション全体またはそのサブセットを、1つのDocker Composeコマンドで起動することができます。

アプリケーション全体の実行

レスポンダのルートにある deploy/docker-compose レスポンダのルートにあるディレクトリには、アプリケーションの4つのバージョンそれぞれのコンポーズファイルが含まれています。JVM 11、JVM 17、Java 11で構築されたネイティブ、Java 17で構築されたネイティブの4つのバージョンそれぞれのコンポーズファイルが含まれています。さらに、 付属の prometheus.yml ファイルを使って、 Prometheusモニタリングを開始することができます。

quarkus-super-heroesディレクトリから、 実行したいアプリケーションのバージョンに応じたコマンドを実行するだけです。例えば、ネイティブのJava 17バージョンを実行するには、 docker-compose -f deploy/docker-compose/native-java17.yml -f deploy/docker-compose/prometheus.yml up を実行します。

scriptsディレクトリには watch-services.shスクリプトが含まれており、別のターミナルで実行することができます。このスクリプトは、すべてのサービスの起動を監視し、すべてのサービスが起動して準備が整ったら報告します。

アプリケーションの起動時にエラーが発生することがあります。これは、あるサービスが、そのサービスが必要とするサービス(データベース、Kafkaブローカーなど)よりも先に起動を完了した場合に発生する可能性があります。すべての起動が完了すると、意図したとおりに動作します。

準備が整い次第、以下のURLで利用可能になります。

アプリケーションのサブセットの実行

個々のサービスは、Docker Composeを介して実行することもできます。

リポジトリ内の各サービスのサブディレクトリの中には、4つのバージョンのアプリケーションのComposeファイルを含む deploy/docker-compose ディレクトリがあります。複数のComposeファイルを1つのコマンドにまとめることができます。

これは、例えば、 Quarkus Dev ModeでFightサービスに取り組み、HeroとVillainサービスを利用できるようにする必要がある場合に便利です。 quarkus-super-heroes ディレクトリから、 実行したいアプリケーションのバージョンに応じたコマンドを実行するだけです。例えば、ネイティブのJava 17バージョンを実行するには、 docker-compose -f rest-heroes/deploy/docker-compose/native-java17.yml -f rest-villains/deploy/docker-compose/native-java17.yml up を実行します。

Quarkus 開発モードでローカルに実行

各サービスは、 Quarkus Dev Modeを介して同時に実行することもできます。各Quarkusサービス( event-statistics, rest-fights, rest-heroes, rest-villains )について、ターミナルを開き、 cd をプロジェクトディレクトリに入れて、 ./mvnw quarkus:dev を実行してください。

Super Heroes UIは ソースからビルドして実行することができますが、この記事の焦点はQuarkusなので、コンテナイメージとして実行します。新しいターミナルを開き、 docker run -p 8080:8080 -e API_BASE_URL=http://localhost:8082 quay.io/quarkus-super-heroes/ui-super-heroes:latest を実行します。

準備が整い次第、以下のURLで利用可能になります。

これで、アプリケーション全体で Quarkus Dev ModeQuarkus Continuous Testingのすべてのメリットを一度に得られるようになりました。すべてのバッキングインフラ(データベース、Kafka、Apicurio)は、 Quarkus Dev Servicesによって自動的にプロビジョニングされます。

アプリケーションをKubernetesにデプロイ

Kubernetesディスクリプターは、Kubernetesの様々なフレーバーに対応しています。 OpenShiftMinikubeKNative、そして「バニラ」 Kubernetesです。

MinikubeとKubernetesのディスクリプターの唯一の違いは、Minikubeのディスクリプターに含まれる全てのアプリケーション Service`が `type: NodePort を使用していることで、 minikube service list を実行するだけで全てのアプリケーションのリストを取得することができます。

KNativeディスクリプタは、5つのアプリケーションのそれぞれに KNative Servingを使用しています。

Docker Composeと同様に、アプリケーション全体またはそのサブセットの 事前に構築されたコンテナイメージを、1つの kubectl apply -f (OpenShiftを使用している場合は oc apply -f )でKubernetesにデプロイすることができます。

レスポンダのルートにある deploy/k8s respositoryのルートにあるディレクトリには、アプリケーションの4つのバージョンそれぞれのKubernetesディスクリプターが含まれています。JVM 11、JVM 17、Java 11で構築されたネイティブ、Java 17で構築されたネイティブの4つのバージョンのKubernetesディスクリプターが含まれています。

例えば、ネイティブのJava 17バージョンをOpenShiftにデプロイするには、単に kubectl apply -f deploy/k8s/native-java17-openshift.yml (または oc apply -f deploy/k8s/native-java17-openshift.yml )を実行します。

アプリケーションに加えてPrometheusモニタリングをデプロイするには、 kubectl apply -f (OpenShiftを使用している場合は oc apply -f )を実行するのに加え、対象となるKubernetes環境に基づいて適切なPrometheus Kubernetes descriptor: prometheus-openshift.yml, prometheus-minikube.yml、または prometheus-kubernetes.yml を実行します。

MinikubeやKubernetesでは、Super Heroes UIとFightsサービスだけがクラスタの外に公開されています。PrometheusやEvent Statisticsサービスにアクセスしたい場合は、 Ingress を使用するか、Podの kubectl port-forward を行って公開する必要があります。OpenShiftでは、すべてのアプリケーションに `Route`が用意されており、クラスター外に公開されています。

さらに、個々のアプリケーションも同様の方法でデプロイできます。リポジトリ内の各サービスのサブディレクトリの中には、同様のKubernetesディスクリプターのマトリックスを含む deploy/k8s ディレクトリがあります。

これらの記述は、本番環境に対応しているとは考えて いません。これらは、できるだけ少ない設定でシステムをデプロイして実行するための基本的なものです。デプロイされたデータベース、Kafkaブローカー、スキーマレジストリは、高可用性を備えておらず、管理や監視にKubernetesのオペレータを使用していません。また、エフェメラルストレージのみを使用しています。

本番対応のKafkaブローカーについては、Kubernetes上で本番対応のKafkaブローカーを適切に展開・設定する方法について、 Strimziのドキュメントをご覧ください。また、 完全にホストされ、管理されたKafkaサービスを試すこともできます!

Apicurio Schema Registryの本番環境については、 Apicurio Registry Operatorのドキュメントをご覧ください。また、 完全にホストされ、管理されたスキーマ・レジストリ・サービスを試すこともできます。

本番環境用のPrometheusインスタンスについては、 Prometheus Operatorのドキュメントで、本番環境用のインスタンスの適切な導入・設定方法をご確認ください。

Kubernetesにデプロイされると、可能性は無限に広がります!上記の同じ例(Fightサービスの開発)を再利用すると、 Quarkus Remote Development Modeを使用してリモートインスタンスをローカルマシンに接続し、 Quarkus 開発モードと同様のエクスペリエンスを得ることができます。ポートフォワーディングの必要はありません。

参加してみませんか?

私たちは常にコミュニティからの参加を求めています。 改良点や バグのリストは常に用意されているので、興味のある方はぜひ参加してみてください。