コンピューティング用にLambdaまたはECSのいずれかを備えたAWSAPIGatewayを使用して「マイクロサービス」アプリケーションを開発しています。現在の問題は、サービス間の通信がAPIゲートウェイを介したAPI呼び出しを介して行われることです。これは、非効率的で安全性が低いと感じます。マイクロサービスをよりパフォーマンスが高く安全な方法で相互に通信させる方法はありますか?どういうわけかプライベートネットワーク内で直接話すように?
私が考えた1つの方法は、複数レベルのAPIゲートウェイです。
しかし、このように、2つのレベルのAPIでルートを「複製」する必要があります...これは理想的ではないようです。多分{proxy+}
を使うと思っていました。つまり、/payment/{proxy+}
は支払いAPIゲートウェイなどに送られますが、APIゲートウェイにはまだ2つのレベルがあります...しかし、これが私ができる最善の方法のようです。
たぶんもっと良い方法がありますか?
マイクロサービスを構築する方法はたくさんあります。 AWSが公開したホワイトペーパーに慣れることから始めます: AWSのマイクロサービス 、 ホワイトペーパー-PDFバージョン 。
あなたの質問であなたは次のように述べました:「問題は、サービス間の通信がAPIゲートウェイを介したAPI呼び出しを介して行われることです。これは非効率的で安全性が低いと感じます。マイクロサービスに話しかける方法はありますかよりパフォーマンスが高く安全な方法でお互いに?」
はい-実際、AWSホワイトペーパー、および API Gateway FAQ APIGatewayをアプリケーションへの「フロントドア」として参照しています。 API Gatewayの目的は、AWSサービスと通信する外部サービスに使用されることです。AWSサービスが相互に通信することはありません。
AWSリソースが相互に通信してマイクロサービスを呼び出す方法はいくつかあります。ホワイトペーパーにいくつか概説されていますが、これは私が使用した別のリソースです: Better Together:AmazonECSとAWSLambda 。あなたが使用するサービスはあなたが持っている要件に基づいています。
モノリシックアプリケーションを小さなマイクロサービスに分割すると、マイクロサービスが相互に通信する必要があるため、通信のオーバーヘッドが増加します。多くの実装では、通信プロトコルとしてREST over HTTPが使用されます。これは軽量プロトコルですが、ボリュームが大きいと問題が発生する可能性があります。場合によっては、統合を検討するのが理にかなっています。大量のメッセージをやり取りするサービス。おしゃべりを減らすためだけにサービスを統合する状況に陥った場合は、問題のあるドメインとドメインモデルを確認する必要があります。
私の理解では、問題の根本はマイクロサービスへのリクエストのルーティングです。 「 マイクロサービスの特性 」を維持するには、ルーティングを管理する単一のソリューションを選択する必要があります。
ルーティングソリューションとしてAPIGatewayを使用するとおっしゃいました。 API Gatewayはルーティングに使用できます...ただし、ルーティングにAPI Gatewayを使用する場合は、ルートを1つのレベルで明示的に定義する必要があります。どうして?
これの欠点は、時間がかかることであり、すでに定義されている既存のAPIを変更しなければならない場合があります。ただし、マイクロサービスのベストプラクティスに従うために、既存のコードベースにすでに変更を加えている場合があります。
ルーティングにAPIGatewayを使用する上記の理由にもかかわらず、適切に構成されている場合、別のリソースがルーティングを適切に処理できます。すべてのマイクロサービスルートが定義されているLambda関数へのAPIGatewayプロキシ、またはルートが定義されている VPC内の別のリソース を使用できます。
あなたがすることはあなたの要件と時間に依存します。すでにどこかにAPIが定義されていて、API Gatewayを使用してリクエストを抑制、監視、保護、およびログに記録したい場合は、プロキシとしてAPIGatewayを使用します。 API Gatewayを最大限に活用したい場合は、APIGateway内の各ルートを明示的に定義してください。どちらのアプローチもマイクロサービスのベストプラクティスに従うことができますが、API Gatewayで各パブリックAPIを定義することがマイクロと連携するための最良の方法であるというのは、私の意見です。 -サービスアーキテクチャ。他の回答も、各アプローチのトレードオフを説明するのに最適です。
ソリューションのラムダを想定しますが、ECSインスタンスまたはELBの場合もあります。
ソリューションに飛び込む前にラムダについて理解する重要な概念の1つは、アプリケーションコードとevent_source
の分離です。
イベントソースは、アプリケーションコードを呼び出す別の方法です。 API Gatewayについておっしゃいましたが、これはラムダ(HTTP REQUEST)を呼び出す唯一の方法です。ソリューションに関連するその他の興味深いevent sources
は次のとおりです。
したがって、HTTP_RESPONSEが、あるラムダが別のラムダを呼び出すことに依存し、その2番目のラムダの結果に依存する場合。直接 invoke を使用するのに十分なソリューションである可能性があります。この方法で、ラムダを同期的にinvoke
できます。また、ラムダはイベントソースとしてAPI Gatewayにサブスクライブし、2つの異なるタイプのイベントを正規化するコードを持っている必要があることも意味します。 (これが、ラムダドキュメントが通常パラメーターの1つとしてevent
を持っている理由です)
HTTP応答が他のマイクロサービス(ラムダ)の実行に依存しない場合。元のラムダが単一のイベントを公開し、そのイベントにサブスクライブされた複数のラムダを並行して実行できるため、このユースケースにはSNSを強くお勧めします。
より複雑なユースケースの場合:
既存のコードベースを実装/変更する柔軟性を排除することなく、現在のセットアップとインフラストラクチャに拘束される以外に、これを行うための複数の方法とアプローチがあります。
API Gatewayの背後にあるサービス間で通信しようとする場合、ループを回避したり、データを公開したり、最悪の場合は自分自身をブロックしたりするために慎重に実装する必要があります。理解を深めるには、「一般的な」画像を参照してください。
サービス間の通信に[〜#〜] http [〜#〜]を使用している間、トラフィックが現在のインフラストラクチャから出て行くのを見るのはよくあることです。同じAPIGatewayを経由して戻ると、代わりに他のサービスを直接配置するだけで回避できます。
たとえば、前の画像では、service B
がservice A
と通信する必要がある場合、APIゲートウェイを経由して戻るのではなく、内部(ELB)エンドポイントを介して通信することをお勧めします。
別のアプローチは、APIゲートウェイで「のみ」[〜#〜] http [〜#〜]を使用し、他のプロトコルを使用してサービス内で通信することです。 、たとえば gRPC 。 (アーキテクチャと既存のコードを変更/適応する柔軟性に依存するため、場合によっては最良の代替手段ではありません)
インフラストラクチャがより複雑で、コンテナ内でオンデマンドで通信できない場合や、エンドポイントに到達できない場合があります。この場合、 イベントドリブンアーキテクチャ (SQS)の実装を試みることができます。およびAWSLambda)
可能な場合はイベント/キューを使用して非同期を実行するのが好きです。私の観点からは、「スケーリング」が向上し、サービスの必要性は不要であるだけでなく、単なるコンシューマー/ワーカーになる必要があります。着信要求をリッスンするために(HTTPは不要)、これは使用方法を説明する記事です この目的のためのrabbitmqはdocker内でマイクロサービスを通信します
これらは、変化が大きすぎてすべてのシナリオが固有であるため、独自の「最良の」方法を見つけるのに役立つ可能性があるいくつかのアイデアです。
あなたの質問はAWSに厳密に関連しているとは思いませんが、サービス間の一般的な通信方法のようなものです。
API Gatewayは、バックエンド境界にあるサービスであり、外部の関係者がアクセスできるエッジサービスとして使用されます。 API Gatewayの背後で、マイクロサービス間で通信するために、APIGatewayを再度通過する必要はありません。
私があなたのケースについて言及したいコミュニケーションの2つの方法があります:
HTTPは、当然のことながら理解しやすく、使いやすいライブラリがたくさんあるため、最も単純な通信方法です。
利点の事実にもかかわらず、注意すべきことがいくつかあります。
メッセージング側では、非同期処理、メッセージブローカーの設定や保守などのインフラストラクチャの問題に対処する必要があります。純粋なHTTPほど簡単には使用できませんが、結果整合性を維持するだけで整合性の問題を解決できます。
全体として、考慮しなければならないことがたくさんあり、すべてがトレードオフに関するものです。マイクロサービスを始めたばかりの場合は、通信にHTTPを使用することから始めて、徐々にメッセージングの代替手段に進むのが最善だと思います。
たとえば、Java + Spring Cloud Netflixの世界では、Feignを使用してEurekaを使用できます。これにより、Eurekaによって実際のIPおよびポートに変換されるサービスへの論理アドレスを非常に簡単に使用できます。また、REST APIにSwaggerを使用したい場合は、そこから Feignクライアントスタブを生成 することもできます。
私はしばらくの間同じ質問をしてきましたが、それでも良い一般的な解決策を見つけることができません...それが価値があるもののために...
通信が一方向であり、「呼び出し元」が結果を待つ必要がない場合、Kinesisストリームは非常に強力です。「タスク」をストリームに投稿し、ストリームにラムダをトリガーさせて処理させます。しかし、明らかに、これは非常に限られたケースで機能します...
応答応答の世界では、エンドユーザーと同じようにAPI Gatewayエンドポイントを呼び出します(HTTPの世界に「適合する」ためにデータをマーシャリングおよびアンマーシャリングするオーバーヘッドが追加され、不要な複数の認証が追加されます)。
まれに、GatewayAPIラムダと他のマイクロサービスの両方から直接呼び出される単一のバックエンドラムダ関数がある場合があります。これにより、「エンドユーザー」に余分な「ホップ」が追加されます([UI->ゲートウェイAPI-> GatewayAPIラムダ]の代わりに、[UI->ゲートウェイAPI->ゲートウェイAPIラムダ->バックエンドラムダ]があります)が、マイクロサービスになります発信された呼び出しはより高速になります(呼び出しと関連するすべてのデータをHTTP要求を介して「トンネリング」する必要がなくなったため)。さらに、これによりアーキテクチャがより複雑になります(公式APIは1つではなくなりましたが、「バックチャネル」の直接依存関係があります)。