私はサーバーアプリケーションのマイクロサービスアーキテクチャについてたくさん読んでいますが、モノリシックアーキテクチャと比較して、内部ネットワークの使用がボトルネックや重大な欠点ではないのではないかと考えています。
正確を期すために、2つの用語の私の解釈を以下に示します。
モノリスアーキテクチャ:すべての機能やデータなどを処理する単一言語の1つのアプリケーション。ロードバランサーは、エンドユーザーからのリクエストを複数のマシンに分散し、それぞれがアプリケーションの1つのインスタンスを実行します。
マイクロサービスアーキテクチャ:機能とデータのごく一部を処理する多くのアプリケーション(マイクロサービス)。各マイクロサービスは、同じマシン上のプロセス間通信や共有メモリとは対照的に、ネットワークを介してアクセスされる共通のAPIを公開します。 API呼び出しは主にサーバー上で固定されてページを生成しますが、おそらくこの作業の一部は、個々のマイクロサービスを照会するクライアントによって行われます。
私の素朴な想像では、マイクロサービスアーキテクチャは、同じマシン(メモリとディスク)上のより高速なリソースとは対照的に、低速のネットワークトラフィックを使用しているようです。内部ネットワークを介したAPIクエリが全体の応答時間を遅くしないことをどのように保証しますか?
多くの場合、内部ネットワークは1 Gbps以上の接続を使用します。光ファイバー接続またはボンディングにより、サーバー間の帯域幅が大幅に向上します。 APIからのJSON応答の平均サイズを想像してください。このような応答のうち、1 Gbpsで1秒間に送信できる応答はどれくらいですか。
実際に計算してみましょう。 1 Gbpsは1秒あたり131 072 KBです。平均JSON応答が5 KBである場合(これは非常に大量です)、1組のマシンのみを使用して、回線を通じて毎秒26 214の応答を送信できます。悪くないですよね?
これが、ネットワーク接続が通常ボトルネックにならない理由です。
マイクロサービスのもう1つの側面は、簡単にスケーリングできることです。 1つがAPIをホストし、もう1つがそれを使用する2つのサーバーを想像してください。接続がボトルネックになった場合は、他の2つのサーバーを追加するだけで、パフォーマンスを2倍にできます。
これは、以前の26 214応答/秒がアプリの規模に対して小さすぎる場合です。他に9つのペアを追加すると、262 140の応答を提供できるようになります。
しかし、サーバーのペアに戻り、いくつかの比較を行ってみましょう。
データベースへのキャッシュされていないクエリの平均が10ミリ秒かかる場合、1秒あたり100クエリに制限されます。 100クエリ。 26 214応答。 1秒あたり26 214の応答速度を実現するには、大量のキャッシュと最適化が必要です(応答が実際にデータベースのクエリなどの有用な処理を必要とする場合、「Hello World」スタイルの応答は適格ではありません)。
私のコンピューターでは、現在、GoogleのホームページのDOMContentLoadedが394ミリ秒発生しました。リクエストが送信された後。 1秒あたりのリクエスト数は3未満です。 Programmers.SEホームページの場合、603ミリ秒発生しました。リクエストが送信された後。これは、1秒あたり2リクエストでもありません。ちなみに、私は100 Mbpsのインターネット接続と高速なコンピューターを使用しています。
ボトルネックがサーバー間のネットワーク速度である場合、これらの2つのサイトは、ページを提供している間、文字通り、さまざまなAPIに対して何千もの呼び出しを行う可能性があります。
これらの2つのケースは、ネットワークがおそらく理論的にはボトルネックにならないことを示しています(実際には、実際のベンチマークとプロファイリングを行って、your特定のボトルネックの正確な場所を特定する必要があります特定のハードウェアでホストされているシステム)。実際の作業(SQLクエリ、圧縮など)に費やした時間と、結果をエンドユーザーに送信する時間は、はるかに重要です。
通常、データベースはそれらを使用するWebアプリケーションとは別にホストされます。これは問題を引き起こす可能性があります。アプリケーションをホストしているサーバーとデータベースをホストしているサーバーの間の接続速度はどうですか?
確かに、接続速度が問題になるケースがあるようです。つまり、データベース自体で処理する必要がなく、すぐに利用できるはずの大量のデータを保存する場合です(これは大きなバイナリファイルです)。しかし、そのような状況はまれです。ほとんどの場合、転送速度はクエリ自体の処理速度と比較してそれほど大きくありません。
転送速度が実際に重要なのは、企業がNASで大きなデータセットをホストしている場合であり、NASは複数のクライアントによって同時にアクセスされます。ここでSANが解決策になる可能性があります。これが唯一の解決策ではありません。Cat6ケーブルは最大10 Gbpsの速度をサポートできます。ボンディングを使用して、ケーブルやネットワークアダプタを変更せずに速度を上げることもできます。その他複数のNASにわたるデータ複製を含むソリューションが存在します。
Webアプリの重要なポイントは、スケーリングできることです。実際のパフォーマンスは重要ですが(より強力なサーバーに誰もお金をかけたくないため)、必要に応じて追加のハードウェアを投入できるため、スケーラビリティははるかに重要です。
特に高速ではないアプリを使用している場合、より強力なサーバーが必要になるため、お金を失うことになります。
スケーリングできない高速なアプリを使用している場合、増大する需要に対応できなくなるため、顧客を失うことになります。
同様に、仮想マシンは10年前にパフォーマンスの大きな問題として認識されていました。実際、アプリケーションをサーバーでホストすることと、仮想マシンでホストすることは、パフォーマンスに重要な影響を及ぼしました。今日、ギャップははるかに小さくなっていますが、まだ存在しています。
このパフォーマンスの低下にもかかわらず、仮想環境はその柔軟性により非常に人気がありました。
ネットワーク速度と同様に、VMが実際のボトルネックであり、実際の規模を考えると、VMなしでアプリを直接ホストすることで数十億ドルを節約できます。しかし、これはアプリの99.9%で何が起こるか:ボトルネックはどこかにあり、VMのために数マイクロ秒の損失があるという欠点は、ハードウェアの抽象化とスケーラビリティの利点によって簡単に補償されます。
マイクロ部分を読みすぎていると思います。これは、すべてのクラスをネットワークサービスで置き換えることを意味するのではなく、モノリシックアプリケーションを適切なサイズのコンポーネントにコンポーネント化し、それぞれがプログラムの側面を処理します。サービスは互いに通信しないため、最悪の場合、大きなネットワークリクエストをいくつかの小さなリクエストに分割します。返されるデータは、とにかく受け取るデータと大きく異なりません(ただし、より多くのデータを返してクライアントに統合する場合があります)。
結果として得られるシステムがモノリシックアプリケーションとして、または構成を介して分散アプリケーションとして実行するのに十分な柔軟性を持つように、コードとリソースアクセスを構造化する。いくつかの一般的なインターフェースの背後にある通信メカニズムを抽象化し、並行性を念頭に置いてシステムを構築すると、すべてを簡単に最適化できますプロファイリングした後システムを実際のボトルネックに見つけます。
多くの人が述べたように、それはネットワークのボトルネックについてではありません。それは、ネットワークの脆弱性についてです。したがって、最初のステップは同期通信を回避することです。思ったより簡単です。必要なのは、適切な境界を持つサービスです。適切な境界により、サービスは自律的で、疎結合で、凝集性が高くなります。良いサービスは別のサービスからの情報を必要としません、それはすでにそれを持っています。優れたサービスが通信する唯一の方法は、イベントを経由することです。優れたサービスも最終的に一貫性があるため、分散トランザクションはありません。
この良さを実現する方法は、まずビジネス能力を特定することです。ビジネス能力は、特定のビジネス責任です。全体的なビジネス価値への貢献。そこで、システム境界について考えるときに取るステップシーケンスを次に示します。
ビジネスサービスには、人、アプリケーション、ビジネスプロセスが含まれることに注意してください。通常、その一部のみが技術的権限として表されます。
これは少し抽象的に聞こえるかもしれないので、おそらく サービス境界の識別の例 はいくつかの興味があるでしょう。
非常に異なる仮定-分散(エンティティレベル)シミュレーションを使用する別の業界から、別の視点を追加したいと思います。概念的には、これは分散型FPSビデオゲームによく似ています。主な違い:すべてのプレーヤーはいくつかの状態を共有しています。データベース呼び出しはありません。すべてがRAM=速度と低遅延のために保持されます)、スループットはそれほど重要ではありません(しかし、完全に無視することもできないと思います)。
参加している各アプリケーションは、モノリス(プレーヤーのすべての面を表す)またはマイクロサービス(群集内の1人のプレーヤーのみを表す)のいずれかと考えることができます。
参加している1つのアプリケーション自体をさらに細かく共有できるマイクロサービスに分解することに関心がありました。通常はシミュレーションにバンドルされている調停または見通し内の計算に損傷を与えます。
問題は、呼び出しのディスパッチと要求の待機の待ち時間です。他の人が指摘しているように、帯域幅はとにかく無関係で豊富です。ただし、見通し内の計算が1マイクロ秒から100マイクロ秒になると(たとえば、すべてのプレーヤーアプリケーション間で共有される新しいマイクロサービスでのキューイングが原因で)、それは大きな損失になります(各更新、数回の更新/秒)。
サービスがどのように機能し、いつ呼び出され、どのデータが交換されるかについて非常に慎重に検討してください。私たちのアプリケーションはすでに位置情報だけを交換するのではなく、推測航法情報を交換します-私は位置xにいて、速度qで方向yに向かっています。そして、これらの仮定が変更されるまで、情報を更新する必要はありません。更新の数が大幅に減り、レイテンシ(それでも問題は発生します)が比例して低くなります。
したがって、細かい頻度で高い頻度でサービスを要求するのではなく、次の方法で頻度を下げてみてください。
次に、システムに関する想定を確認することを忘れないでください。レイテンシよりもスループットに関心がある場合、または状態を共有していない場合などは、必ず、意味のあるマイクロサービスを使用してください。意味がわからないところでは使用しないでください。
あなたの素朴な想像力は正しいです。そして、それはしばしば問題ではありません。現代の機械は高速です。マイクロサービスアーキテクチャの主な利点は、開発と保守の労力と時間に見られます。
そしてもちろん、共有メモリを使用したり、1つの実行可能ファイルに複数のサービスを物理的にデプロイすることさえできないというルールはありません。それに依存しないように設計する限り。
現在の回答に追加するもう1つの要素。 coarse-grained services を使用します。すべての呼び出しからの待ち時間を避けたいので、10回の呼び出しを行う代わりに、DTOで必要な10個のデータを取得する呼び出しを行います。
また、マイクロサービスは人々が考えるほどマイクロではないことを覚えておいてください。