ModernJavaEEDesignPatterns / Microservices Design Pattern


ModernJavaEEDesignPatterns

第5章 Microservicesデザインパターン

  • DDDの助けを借りたアプリケーションの機能分割は、microservicesアーキテクチャを構築するための前提条件だ。このアプローチだけが、効果的に疎結合で高凝集な設計をすることができる。はるかに簡単なサービス特性ですすめる場合でさえ、既存のアプリケーションを分解することができる。しかしながら、フロントエンドによって結ばれているアプリケーションとは異なり、microservicesは互いに相互作用し、サービスコールのネットワークにまたがることができる。分かりやすくと保守しやすい相互作用の多様性を維持するために、最初のパターンのセットはサービスの相互作用をモデル化することが役立つこと明らかにした。これらのパターンは、最初にArun Gupta氏によって発表されたが、このレポートで改訂された。

一般的な原則

  • すべてのmicroserviceは考慮される必要があるいくつかの一般的な基本原理をもっている。これらは、17ページの「サービスの特性」、19ページの「Microservicesベストプラクティス」の核心の要約に派生(由来)する。

Trunk コンフリクトを回避するために、各Microserviceは独自のビルドとする

  • 各microserviceを別々のビルドに管理する。この理由の1つは、チームがプロダクション環境に新しいバージョンを置くのに完全な責任を負うことができることだ。また、リポジトリを照会することによって、必要な下流のサービスを正しいリビジョンで利用することをチームに可能にします。26ページの「Independently Deployable and Fully Contained(独立して展開可能と完全に自律している)」と比較しなさい。

ビジネスロジックはステートレス

  • ステートレスとしてサービスのロジックを扱う。様々なサービス間で状態をレプリケートする必要があるのは、悪いデザインの説得力のある指標だ。サービスは完全に自立し、独立し、どのような事前設定された状態もなしに動作することができる必要がある。第3章と比較しなさい。

データアクセス層は、キャッシュされる

  • 最小限へとサービスの応答時間を保つために、構築したすべてのサービスのデータ・キャッシングを検討する必要がある。そして、24ページの「Design for Performance(パフォーマンスのためのデザイン)」に留意しなさい。

各Microserviceのために別々のデータストアを作成する

  • 21ページの「Design for Integrity(整合性のためのデザイン)」22ページの「Design for Data Separation(データ分離のためのデザイン)」とを比較してください。

集約パターン(Aggregator Pattern)

  • microservicesで使用される最も単純なパターンは、集約パターン(図5-1)だ。これは、EIPカタログから既によく知られており、有用なmicroservicesアーキテクチャであることが判明している。このパターンの主な目的は、サービスコールと識別からのレスポンスのストリームを受信するか、または相関しているレスポンスを認識する特殊なフィルタとして振る舞うことだ。すべてのレスポンスが集約されたら、アグリゲータは、それらを相関させ、次なる処理のためのクライアントへの1つレスポンスを発行する。 その最も基本的な形式では、アグリゲータは、特定のユースケースで必要とされる機能を実現するために複数のサービスを呼び出す単純な、SPA(例えば、AngularJS)だ。この例ですべての3つのサービスがRESTインターフェースを公開していると仮定すると、アプリケーションは単にデータを消費してそれをユーザーに公開する。この例のサービスは、アプリケーション・サービス(上記の比較)であるべきであり、フロントエンド内に任意の追加のビジネスロジックを必要としてはならない。もしそれらがドメインサービスを表す場合は、最初にアプリケーションサービスによって呼び出され、そして表現可能な状態にする必要がある。
  • 図5-1。集約パターン(Aggregator Pattern)
  • エンドポイントは必ずしもRESTベースである必要はない。異なるプロトコルを使用することは全く有効です。アグリゲータは重度に非同期ドメインサービスにアクセスする別のビジネスサービスであるため、それは関連するプロトコル(例えば、JMS)を使用して、メッセージ駆動型アプローチを採用しています。

プロキシパターン(Proxy Pattern)

  • プロキシパターンは、プロキシ(図5-2)のようにラッパーサービスを作成することによって、サービスに追加のインタフェースを提供することができる。ラッパーサービスでは、そのコードを変更することなく、目的のサービスに機能を追加することができる。
  • 図5-2。Proxyパターン
  • プロキシは、単純なパススループロキシのことがあり、その場合にはただプロキシサービスのいずれかにリクエストを委譲するだけだ。プロキシサービスの内部で追加のロジックがある場合には
  • これは通常、スマートプロキシと呼ばれている。適用可能なロジックは様々に異なり、単純なログからトランザクションを追加するまで幅をと持つことができる。ルータとして使用する場合は、パラメータまたはクライアントのリクエストによって異なるサービスにもリクエストをプロキシすることができる。

パイプラインパターン(Pipeline Pattern)

  • より複雑なシナリオでは、1つのリクエストが完全な一連の手順の実行をトリガする。この場合、1つのレスポンスのために呼び出されなければならないサービスの数は1つ以上になる。サービスのパイプラインを使用すると、到着したリクエスト(図5-3)上とは異なる操作の実行を可能にする。パイプラインは、同期的または非同期的にトリガすることができるが、処理ステップで最も可能性が高いのは同期で互いに依存する。
  • サービスが同期要求を使用している場合でも、クライアントはパイプラインの最後のステップが終了するのを待つ必要がある。
  • 図5-3。パイプラインパターン(Pipeline Pattern)
  • 同期的に呼び出された場合、チェーンは、一定の時間を超えてはならない。大体のルールとして、ユーザビリティ調査によると、1/10秒が、ユーザーがシステムが瞬時に反応していることを感じる限界だ。一秒は、ユーザが遅延に気づくだろうにも関わらず、中断のない考えるユーザーフローの限界だ。通常、特別なフィードバックは以上0.1未満1.0秒の遅延時に必要ない。しかしユーザーがデータを直接操作する感覚を失う。10秒は、ユーザの注意を対話に焦点を当て、保つための限界だ。

共用リソース(Shared Resources)

  • microservicesの重要な設計原則の一つは、自律性です。特に、移行シナリオ(43ページの「マイグレーション・アプローチ」を参照)で、数年前の設計ミスを修正するのは難しいかもしれない。ビッグバンに手を伸ばす代わりに、これらの特殊なケースを処理することは、より合理的な方法かもしれない。
  • microservicesが共通のデータソースを共有する必要な状況に陥ることは理想的ではない。しかし、それは「共有リソース」パターン(図5-4)で回避できる。ここで重要なのは、密接に関連するビジネスドメインを維持しており、ルールとしてこの例外を取り扱っていないことだ。それはアンチパターンと考えることもできるが、ビジネスのニーズはそれが必要な場合がある。そうは言っても、それは確かにグリーンフィールドアプリケーションのためのアンチパターンだ。
  • 図5-4。共用リソース(Shared Resources)

非同期メッセージング(Asynchronous Messaging)

  • 典型的なRESTfulなデザインパターンはmicroservicesの世界では一般的だ。ほとんどの場合、彼らは同期ため、ブロッキングの方法で実装されている。これは、Java EEに変更することができ、実装が非同期呼び出しをサポートしている場合でも、それはまだあなたが構築しようとしているエンタープライズシステムにおいては第二級市民と見なされる可能性がある。メッセージ指向ミドルウェア(MOM)は、この分野での統合およびメッセージングの問題へのより合理的な解決策だ。特にホスト・システムによって公開され、MOMを介して接続されているmicroservicesに来る場合は。REST要求/応答およびパブリッシュ/サブスクライブメッセージの組み合わせは、ビジネス・ニーズ(図5-5)を達成するために使用されるだろう。
  • 図5-5。非同期メッセージング