Skip to content

A repository that defines the parent pom and common CI/CD pipeline of the microservice version rental reservation management system

Notifications You must be signed in to change notification settings

extact-io/msa-rms-parent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rental Management System Application with MSA

Rental Management System(RMS)はHelidonを使ってマイクロサービスやMicroProfileの利用法や効果を確認することを目的としたリファレンス的なアプリケーションです。このリポジトリはRMSの説明や親pom、GitHub Actionsの共通的なワークフローなどRMS全体で共通となる情報や定義を格納したものになります

Table of Contents

アプリケーション機能

RMSは会員がレンタル品を予約するアプリケーションで管理機能としてマスターデータをメンテナンスする機能を持っている。なお、実装している機能は予約まででレンタルを行う機能はまだ持っていない

分類 機能 内容
会員機能 レンタル品検索 レンタル品を検索し予約状況の確認ができる
レンタル品予約 予約したいレンタル品を選択しレンタル期間を指定した予約ができる
予約確認 自分の予約を確認したりキャンセルしたりすることができる
管理機能 レンタル品管理 レンタル品の登録や更新などを行うことができる
予約管理 登録されたレンタル予約の削除や変更を行うことができる
ユーザ管理 ユーザの登録や更新、削除などを行うことができる
共通機能 ログイン/ログアウト システムへのログインとログアウト
ユーザプロファイル ユーザが自分の登録情報を確認、変更ができる

💁 INFO
手っ取り早く動くものを見たい方はこちらのデモアプリをお試を

マイクロサービスの構成

RMSは次のアプリケーションから構成されるマイクロサービスアーキテクチャになっている

service_overview

DBはh2のインメモリデータベースを使ったDatabase per Service構成にしている

要素 説明
ApiGateway 主に以下の役割を担う
- フロントエンドに対するFacade
- フロントエンドとバックエンドのデータモデルの変換
- ユーザ認証と後段サービスへの認証情報の伝播
RentalItemService レンタル品を管理するサービス
ReservationService 予約を管理するサービス
UserService ユーザを管理するサービス
SPAクライアント ReactによるSPAのUIアプリ
CLIクライアント JavaSEによるコンソールUIアプリ

なお、SPA,CLIのどちらでもレンタル品の予約や管理を行うことができるが、CLIアプリはSPAアプリよりもできることが少なくなっている。

⚠️ WARNIG
サンプル的な側面があるため小さいサービスでマイクロサービスを構成しているが、実業務でこのような小粒度のサービスをマイクロサービス化することは勧めない。マイクロサービスアーキテクチャで得られるメリットよりもデメリットの方が遥かに大きくなる可能性が高い

repository構成

RMSを構成する各アプリケーションやライブラリは次のようにマルチレポ形式で管理している

repository 説明
msa-rms-parent 親pomや共通的なGitHub Actionsのワークフローなどの共通定義を格納しているこのリポジトリ
msa-rms-platform サービスに依らない基盤的な仕組みを提供する。このリポジトリ内だけはMavenのマルチモジュールによるモノレポ形式になっている。詳細はレポジトリのREADMEを参照
msa-rms-apigateway ApiGatewayを格納するリポジトリ
msa-rms-service-item RentalItemServiceを格納するリポジトリ
msa-rms-service-reservation ReservationServiceを格納するリポジトリ
msa-rms-service-user UserServiceを格納するリポジトリ
msa-rms-ui-console RMSのコンソールアプリを格納するリポジトリ

Reactアプリのrepository構成

ReactアプリのrepositoryにはApiGatewayのソースコードからMicroProfile OpenAPIで出力したOAS情報(openapi.yml)をもとにOpenAPI Generatorで自動生成したAPI Clientのrepositoryも含まれる。このrepository間の関係は次のとおり

react_rep_relations

repository 説明
rms-ui-react ReactによるrmsののSPAフロントエンドアプリのリポジトリ
rms-generated-client-js OpenAPI Generatorで生成したAPI Clientコードを格納するリポジトリ
msa-rms-apigateway openapi.ymlを出力するアプリのリポジトリ

システムアーキテクチャ

RMSはローカルでも動作するがAWS上の次の構成をアプリのターゲット環境としている。なお、CI/CDにはGitHub ActionsをContainerRegistryにはGitHub Packagesを使っている。

RMSのシステム全体像

aws_arch

サービスを稼働させるコンテナ環境は次のとおり

サービス 稼働環境
ApiGateway EC2(Installed Docker)
RentalItemService ECS(Fargate)
ReservationService ECS(Fargate)
UserService ECS(Fargate)

データを管理するサービスはPrivate subnetに配置することのみを必須とし、その他はデモ環境でもあるため、コストを最優先の構成にしている。よって、敢えてシングルAZ構成で高額なALBも利用していない

💁 INFO
実際のアプリのお試しはこちらからどうぞ

ℹ️ 関連記事
1日50円で使えるマイクロサービスなアプリを動かすAWS環境を作ってみた | 豆蔵デベロッパーサイト

CI/CD環境

上述のとおり、CI/CD環境はすべてGitHubのサービスでまかなっている。

  • JavaのコンパイルからコンテナイメージのContainerRegistryへのpushまでの操作はすべてMavenで行いってる
  • コンテナイメージのbuildからpushの定義は親pomdocker-maven-pluginを使って行っている
  • コンテナイメージのtagはGitHub Actionのbuild-to-repo-job.ymlでgitのコミットハッシュをつけている
  • EC2のDockerコンテナ上で稼働するApiGatewayへのデプロイはdeploy-to-ec2-job.ymlでビルドしたコミットハッシュのコンテナイメージを起動するように書き換えたシェルスクリプトをAWS CodeDeployでEC2にデプロイし、コンテナを再起動している
  • Fargate上の各サービスのデプロイはdeploy-to-ecs-job.ymlでAWS CLIでコンテナのtagをコミットハッシュに書き換えた新しいリビジョンのタスク定義を作成し、サービスを更新することで再デプロイを行っている

ℹ️ 関連記事
今さら聞けないMaven – コンテナのビルドと一緒にpushもMavenでしたい。 | 豆蔵デベロッパーサイト

アプリケーションアーキテクチャ

利用ライブラリと準拠API

RMSで利用、採用している主なものは下記のとおり

論理アーキテクチャ

ApiGatwayやReservationServiceなどのバックエンドアプリはいずれも次に示すdomainレイヤをリラックスレイヤにした一般的なレイヤーアーキテクチャを採用している

layer_arch

  • webapi・・レンタル予約システムアプリをRESTで外部に公開する
  • Serivce・・レンタル予約システムのアプリケーション実装
  • domain・・エンティティや制約
  • external・・RESTによるアプリ間連携を行う
  • persistence・・データの永続化
  • platform-fw・・アプリ間で共通となる制御構造や処理の流れを実装したRMS向けフレームワーク
  • platform-core・・処理形態および業務依らない基盤的な仕組み

レイヤ間やパッケージやライブラリへの依存関係のルールはArchUnitの実装で細かく定義している

📌 POINT
Persistenceレイヤは設定を切り替えるだけでFileによる永続化とJPAを使ったRBDへの永続化のどちらでも使えるようにしている

ℹ️ 関連記事
ArchUnitで考えるアーキテクチャ構造とその検証 | 豆蔵デベロッパーサイト

MicroProfileを使った主な仕組み

MicroProfileの機能を使って実現しているRMSアプリケーションの主な仕組みは以下のとおり

MicroProfile Config

モジュールごとにデフォルト値を設定した設定ファイルをそれぞれ持ち、実行環境ごとに定義が必要な設定はMicroProfile Configの優先度の仕組みを使い、環境変数で設定を上書きするようにしている。

各モジュールが持つMicroProfile Configの設定ファイルと優先度は次のとおり

モジュール 設定ファイル 優先度 内容
(環境変数) (docker_run) 300 rms.*で定義している設定キーは実行環境ごとに環境変数で上書きされることを期待している
apigateway application.yaml 100 apigateway向けの設定を定義
item-service application.yaml 100 item-service向けの設定を定義
reservation-service application.yaml 100 reservation-service向けの設定を定義
user-service application.yaml 100 user-service向けの設定を定義
console-ui application.yaml 100 console-ui向けの設定を定義
platform-fw application.yaml 50 fwが持つ機能のデフォルト動作などを定義
platform-core application.yaml 30 coreが持つ機能のデフォルト動作などを定義

パスフレーズなどの機密情報はターゲット環境のセキュアな領域に配置された定義を読み込むようにしている。なお、MicroProfile ConfigのConfig Profile機能はYAMLが使えないなど使いづらい部分があるため使用していない

ℹ️ 関連記事
お手軽便利MicroProfile Config | 豆蔵デベロッパーサイト
MicroProfile Config 3.0へのキャッチアップ | 豆蔵デベロッパーサイト

MicroProfile Rest Client

RMSでは次の箇所でMicroProfile Rest Clientの機能を使っている

  • REST呼び出し(RestClinetインタフェース)
    • 例えばApiGatwayからReservationServiceの呼び出しはReservationApiRestClientで、ReservationServiceからRentalItemServiceへの呼び出しはRentalItemCheckApiRestClientで行っている
    • 他についてもRMSではMicroProfile Rest ClientのRestClientインタフェースを使って対向サービスへのREST呼び出しを行っている
  • REST呼び出しにおけるHTTPヘッダの設定(ClientHeadersFactory)
    • ApiGatwayと各サービス間は閉域ネットワークのため、ApiGatewayから各サービスに伝播する認証情報はMicroProfile Rest ClientのClientHeadersFactoryを実装したPropagateLoginUserClientHeadersFactoryでHTTPヘッダーに平文で設定を行っている
    • Console-UIはサーバーで発行されたIDトークン(JWT)を常にAuthorizationヘッダに設定する必要があるがこれについても、ClientHeadersFactoryを実装したPropagateJwtClientHeadersFactoryで行っている
  • REST呼び出しに対する例外ハンドリング(ResponseExceptionMapper)
    • Responseのステータスコードが400番台や500番台のエラーを示している場合、アプリにはそのエラーに応じた例外を返却するようにMicroProfile Rest ClientのResponseExceptionMapperを使い、PropagateResponseExceptionMapperでResponseに対するエラーハンドリングを一元的に行っている

ℹ️ 関連記事
らくらくMicroProfile RestClient | 豆蔵デベロッパーサイト
MicroProfile RestClient 3.0の確認と小技機能の紹介 | 豆蔵デベロッパーサイト

MicroProfile OpenAPI

<OAS情報の定義>

RMSではMicroProfile OpenAPIを使いソースコードをもとにOAS(openapi.yml)を生成するスキーマファーストではなく、ソースコードを起点にしたボトムアップアプローチを採っている

具体的にはアプリケーションに固有なAPI情報はアプリのRESTインタフェースにMicroProfile OpenAPIのアノテーションを使いOAS情報を定義している。このアノテーションが使われているアプリのインタフェースは次のとおり

これに対しエラーステータスなどアプリで共通となる情報はplatform-fwのCommonOpenApiModelReaderでMicroProfile OpenAPIのプログラムAPIを使いコードでOAS情報を定義し、それを各アプリが参照する形にしている

また、OASで扱う共通的な型情報については、platform-coreのapplication.yamlでMicroProfile OpenAPIの設定機能で行っている

<OAS情報の生成>

MicroProfile OpenAPIは/openapiのリクエストに対しソースコードの情報をもとにリアルタイムでOAS情報(openapi.yml)を生成してレスポンスとして返す。このため、OpenAPI Generatorでopenapi.ymlファイルをもとにコード生成を行う場合、あらかじめ/openapiのレスポンスをファイルに出力しておく必要がある。

RMSでは/openapiを呼び出してファイル出力するGenerateOasFileTestを用意し、このテストクラスを使ってopenapi.ymlを生成するようにしている

<OAS情報の参照>

Helidonの独自機能となるがOpenAPI UI機能を使うことで、/openapiのレスポンスをこちらのようなswagger-uiで簡単にみることができる

ℹ️ 関連記事
コードが仕様の源泉MicroProfile OpenAPI | 豆蔵デベロッパーサイト
MicroProfile OpenAPI 3.0の新機能と既存機能の比較 | 豆蔵デベロッパーサイト

MicroProfile JWT Auth

RMSではID/Passwordによる独自のログイン機能を用意し、ログイン成功時にJWTを発行し、クライアントは以降のリクエストではAuthorizationヘッダのbearerトークンに発行されたJWTを設定する。これに対しサーバーサイドは認証配下のリクエストに対し常にJWT認証を行う

RMSではこのJWT認証にMicroProfile JWT Authの機能を使って実現している。MicroProfile JWT Authを利用する上で必要な実装はなく、ApiGatewayApplicationのように認証配下とするRESTリソースを管理するJAX-RSのApplicationクラスに@LoginConfig(authMethod = "MP-JWT")を付けるだけとなる

また、MicroProfile JWT Authとは関係ないが、ログイン成功時にJWTを発行する仕組みはplatform-coreのjwtパッケージに、そして発行されたJWTをクライアントに伝播させる仕組みはplatform-fwのloginパッケージに実装している

JWTを生成する処理はAuth0 java-jwtを使ったAuth0RsaJwtGeneratorjose4jを使ったJose4jRsaJwtGeneratorを用意している

ℹ️ 関連記事
基本から理解するJWTとJWT認証の仕組み | 豆蔵デベロッパーサイト
MicroProfile JWT Authがやってくれること・できること | 豆蔵デベロッパーサイト
Auth0 java-jwtを使った素のJWT認証 | 豆蔵デベロッパーサイト
続・Auth0 java-jwtを使った素のJWT認証 - 公開鍵方式でやってみた | 豆蔵デベロッパーサイト

MicroProfile Health

RMSではコンテナに対する独自のヘルスチェックコマンドとして、MicroProfile HealthのReadiness Probeを実装している

DBを持つサービスにはping sqlを発行し、DBの死活状態を確認するDbReadinessCheckを、そしてApiGatewayのように他のサービスへ連携を行うサービスについては、設定で定義されたすべての連携先に対してReadiness Probe(/health/ready)を行いすべてOKなら自身のステータスもOKとするReadinessOfOutboundServersHealthCheckを用意している

ℹ️ 関連記事
MicroProfile Healthの機能と利用 | 豆蔵デベロッパーサイト

MicroProfile Metrics

RMSでの利用はなし
(MicroProfile Metricsがデフォルトで取集するメトリクスに対するGrafanaの素敵なダッシュボードがないため。誰か作って・・)

ℹ️ 関連記事
MicroProfile Metricsの機能と利用 | 豆蔵デベロッパーサイト

MicroProfile OpenTracing

RMSではMicroProfile OpenTracingとJaegerで分散トレース情報の収集と参照を行っている

MicroProfile OpenTracingの利用は簡単で、必要なライブラリをアプリケーションに組み込むだけで利用可能となる。よって、通常の利用方法において必要となる実装はない

ただし、RMSでは一部非同期によるREST呼び出しを行っている箇所があり、この箇所におけるトレース情報の伝播がMicroProfile OpenTracingのデフォルトの機能では行われないため、MicroProfile OpenTracingのAPIを使って、マニュアルでトレース情報を対向システムに伝播するようにしている。この実装はReservationGwServiceのcomposeModelメソッドで行っている

なお、RMSの実際の分散トレースはこちらから参照することができる

ℹ️ 関連記事
MicroProfile OpenTracingとJaegerで理解する分散トレーシング | 豆蔵デベロッパーサイト

MicroProfile Fault Tolerance

RMSでは、REST連携する対向システムがダウンしている際に未処理のリクエストが溜まり連鎖的に障害が発生することを防ぐため、RentalItemApiProxyなどREST連携を行う箇所でサーキットブレーカーを下記のように設定している

@NetworkConnectionErrorAware
@CircuitBreaker(
        requestVolumeThreshold = 4, 
        failureRatio=0.5, 
        delay = 10000, 
        successThreshold = 3,
        failOn = RmsNetworkConnectionException.class)
public class RentalItemApiProxy implements RentalItemApi {..

この設定内容は次のとおり

  1. @NetworkConnectionErrorAwareによりネットワークエラーはRmsNetworkConnectionExceptionに変換される
  2. RmsNetworkConnectionExceptionを失敗としてカウントし、それ以外の例外が発生しても失敗にはカウントしない
  3. 直近処理した4件の失敗率が0.5、つまり2件以上であった場合にサーキットブレーカーをopenにし、以降10秒間のメソッド呼び出しに対してはCircuitBreakerOpenExceptionを送出する
  4. 10秒経過後、3回連続して処理が成功した場合、つまりCircuitBreakerOpenException以外が返却された場合に正常状態に復帰する
  5. 3回連続する前に処理が1度でも失敗した場合は、3.に戻り同様の制御を繰り返し行う

ℹ️ 関連記事
MicroProfile Fault Tolerance(1) - 例で理解する基本機能編 | 豆蔵デベロッパーサイト
MicroProfile Fault Tolerance(2) - 例で理解する非同期編 | 豆蔵デベロッパーサイト
MicroProfile Fault Tolerance(3) - 例で理解する設定編 | 豆蔵デベロッパーサイト

About

A repository that defines the parent pom and common CI/CD pipeline of the microservice version rental reservation management system

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages