私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

序文

これまでの数回の記事の後、サービスの公開方法、サービスがレジストリに登録されるタイミング、サービスの導入方法、サービスの全体的な呼び出しプロセスなど、Dubboプロセス全体を誰もが明確に理解していると思います。

ただし、詳細に説明されていないもう1つの非常に重要な点があります。それは、Dubboのクラスター障害耐性です。

オンラインサービスはクラスターで展開する必要があります。相互にバックアップするには少なくとも2つ必要です。次に、サービスの利用者がどのプロバイダーに電話をかけるかという疑問が生じます。通話が失敗した場合はどうすればよいですか?

このとき、クラスター耐障害性機能が役立ちます。今日は、ダボのクラスター耐障害性の波を詳細に分析します。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

呼び出し元とは何ですか?

実際、私は以前にこれを言いました、そしてそれは本当に重要なので、今日またそれをレビューします。

Dubboでは、呼び出し元は実際には呼び出し関数を持つオブジェクトです。サービス公開側でカプセル化されるのは実際のサービス実装であり、実際のサービス実装は呼び出し元にカプセル化されます。

サービス導入側では、サービスプロバイダーの構成情報をレジストリから取得し、構成情報の一部を呼び出し側にカプセル化します。この呼び出し側はリモートで呼び出すことができます。もちろん、injvmプロトコルを使用する場合、実際の呼び出しはローカルのままです。

次に、ClusterInvokerがあります。これは、サービスの導入によって生成された呼び出し元をカプセル化し、クラスターの障害耐性やその他の機能を提供する呼び出し元でもあります。この呼び出し元は、コンシューマーに公開される呼び出し元です。

したがって、Dubboは、呼び出し元に呼び出すことができるすべてのサービスオブジェクトをカプセル化する統合モデルです。

クラスター障害耐性は消費者側で実装されているため、今日は主に消費者へのサービスについて話します。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

サービスカタログとは正確には何ですか?

サービスディレクトリはディレクトリでもあります。実際、以前に導入されたことがありますが、個別に言及されているわけではありません。すべての人にわかりにくい場合があります。今日はそれを見てみましょう。

サービスカタログとは正確には何ですか?名前はサービスカタログであり、そこからリモートサービスを見つけることができますか?

半分正しい!リモートサービスはサービスディレクトリから見つけることができますが、これは「ディレクトリ」ではなく、実際には一連の呼び出し元のコレクションです。

前述のように、サービスプロバイダーはクラスターで展開されます。すべての同じサービスに複数のプロバイダーが存在するため、それらを収集するためにサービスカタログを設定します。選択する場合は、サービスカタログから選択します。

また、サービスプロバイダーは静的ではありません。たとえば、サービスプロバイダーがクラスターに追加された場合、呼び出し元を対応するサービスカタログに追加し、サービスプロバイダーをオフラインにし、対応する呼び出し元をカタログから削除する必要があります。変更された構成も更新する必要があります。

したがって、このサービスディレクトリは、実際にはレジストリを監視する機能を実装しています(RegistryDirectoryを参照)。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

このノードはそのままにしておきます。主にDirectoryに依存します。通常の操作では、抽象クラスを使用してDirectoryインターフェイスを実装します。抽象クラスは、いくつかのパブリックメソッドを実装し、ロジックを定義します。次に、特定の実装がサブクラスによって完了します。2つあることがわかります。サブカテゴリはStaticDirectoryとRegistryDirectoryです。

RegistryDirectory

最初にRegistryDirectoryを見てみましょう。これは動的ディレクトリです。特定の構造を見てみましょう。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

スクリーンショットから、RegistryDirectoryがDemoServiceの2つのサービスプロバイダーURLと対応する呼び出し元を格納していることがわかります。

また、上記の継承構造から、NotifyListenerインターフェイスを実装しているため、レジストリの変更を監視できることもわかります。サービスセンターの構成が変更されると、RegistryDirectoryは変更の通知を受信し、構成に従って呼び出し元リストを更新できます。 。

したがって、RegistryDirectoryには次の3つの機能があります。

  1. 呼び出し元のリストを取得する
  2. レジストリの変更を監視する
  3. 呼び出し元を更新します。

呼び出し元のリストを取得するために、RegistryDirectoryによって実装された親クラスの抽象メソッドdoListは呼び出し元のリストを取得することを目的とし、その内部実装は主にレイヤーメソッド名をフィルター処理し、メソッド名で対応する呼び出し元を見つけることです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

レジストリの変更を監視し、NotifyListenerインターフェイスを実装することにより、レジストリのデータの変更を認識します。これは、サービスが導入されたときに実際にサブスクライブされます。

 public void subscribe(URL url) {
        setConsumerUrl(url);
        registry.subscribe(url, this); //订阅
    }

RegistryDirectoryは、3つのコレクション、つまり、invokerUrls、routerUrls、およびconfiguratorUrlsを定義して、対応する構成変更を処理し、それらをオブジェクトに変換します。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

Invokerリストの更新は、実際には、変更を監視するInvokerUrls、refreshInvoker(invokerUrls)に基づいて一連の操作を実行し、構成に従ってInvokersを更新します。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

簡単に言うと、最初に、invokerUrlの数に基づいてすべての呼び出し元を無効にするかどうか、およびプロトコルヘッダーが空かどうかを決定します。無効にしない場合は、URLをInvokerに変換して、<url、Invoker>のマッピング関係を取得します。

次に、変換を実行して<メソッド名、呼び出し元リスト>のマッピング関係を取得し、同じグループの呼び出し元をマージして、マージした結果をmethodInvokerMapに割り当てます。このmethodInvokerMapは、上記のdoListで使用されているマップです。

したがって、methodInvokerMapはrefreshInvoker中に構築され、呼び出し時にmethodInvokerMapが読み取られ、最後に役に立たない呼び出し元が破棄されます。

StaticDirectory

StaticDirectory、これは複数のレジストリで使用されます。これは静的ディレクトリです。つまり、固定されており、増減しません。すべての呼び出し元は、コンストラクタを介して渡されます。

単一のレジストリで構成した参照が複数のプロバイダーに対応し、複数の請求書を生成し、管理のためにそれらをRegistryDirectoryに保存することは簡単に理解できます。呼び出しを容易にするために、1つの請求書のみが外部に公開されてカプセル化されます。内部の複数の呼び出し元の状況。

複数のレジストリには複数のカプセル化された呼び出し元があり、これも選択に直面するため、StaticDirectoryを使用してこれらの呼び出し元を管理用に保存し、カプセル化して1つの呼び出し元のみを公開して簡単に呼び出すことができます。

動的に変更できるサービスとは異なり、構成には複数のレジストリが書き込まれるため、静的です。

StaticDirectoryの内部ロジックは非常に単純です。つまり、リストにこれらの呼び出し元が格納され、親クラスを実装するメソッドは何もせずにリストを返すだけです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

サービスルーティングとは何ですか?

サービスルーティングは、実際には、サービスコンシューマーが呼び出すことができるサービスプロバイダーを指定するルーティングルールです。Dubboには、ConditionRouter、ScriptRouter、およびTagRouterの3種類のルーティングがあります。

最も一般的に使用されるのは条件付きルーティングです。条件付きルーティングを分析します。

条件付きルーティングは、[サービスコンシューマーマッチング条件] => [サービスプロバイダーマッチング条件]の形式の2つの条件で構成されます。たとえば、公式Webサイトはホスト= 10.20.153.10 =>ホスト= 10.20.153.11です。

このルールは、IP 10.20.153.10のサービスコンシューマーは、IP 10.20.153.11のマシンでのみサービスを呼び出すことができ、他のマシンでサービスを呼び出すことはできないことを示しています。

これはルーティングと呼ばれます。

ルーティング構成もRegistryDirectoryの通知を通じて更新および構築され、ルーティング呼び出しは呼び出し元が更新されたときに行われます。具体的には、toMethodInvokersが呼び出されたときにサービスレベルのルーティングとメソッドレベルのルーティングが実行されます。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

特定のルーティングマッチングと式の解析は詳細ではありません。興味のある学生は自分で理解します。実際、彼らはこの機能が何をするのかを知っています。とにかく、ルーティングフィルタリングの後、消費者は呼び出すことができるリモートサービスを取得します。

Dubboのクラスターの用途は何ですか?

サービスカタログがあることはすでに述べましたが、カタログはルーティングルールによってフィルタリングされています。現時点では、まだ多数の呼び出し元があります。消費者は決定を下す必要があります。では、どの呼び出し元を呼び出す必要がありますか?

選択した呼び出し元がエラーを起こした場合はどうすればよいですか?先に述べたように、これはクラスターがステージに登場するときです。これにより、この一連の呼び出し元がclusterInovkerにカプセル化され、1つの呼び出し元のみがコンシューマーに呼び出されます。

次に、呼び出し元の選択、呼び出しが失敗した場合の呼び出し元の変更など、clusterInovker内でさまざまな操作を実行できます。

これらの詳細はカプセル化されており、消費者はこの複雑さを感じることができないため、クラスターは、サービスプロバイダーから消費者を保護し、消費者の使用を簡素化する中間層です。

また、さまざまなクラスター障害耐性対策を置き換える方が便利です。

Dubboには多くのデフォルトのクラスター実装があり、主に次のとおりです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

各クラスターは実際にはXXXClusterInvokerを返します。FailoverClusterの例を挙げましょう。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

降りてくるだけで、各クラスターを通過します。

FailoverClusterInvoker

このクラスターは自動フェイルオーバー機能を実装しています。簡単に言えば、リモートコールが失敗すると、すぐに別のコールに変更されます。もちろん、再試行もあります。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

doInvokeメソッドは、最初に再試行回数を取得し、次に再試行回数に基づいてループ呼び出しを行い、例外をキャッチし、失敗後に再試行することがわかります。

各サイクルは、ロードバランシングを介して呼び出し元を選択し、次にこの呼び出し元を介してリモート呼び出しを行います。失敗した場合は、例外を記録して再試行します。

この選択には実際にはスティッキープロセスがあります。つまり、最後に選択された呼び出し元が記録されるため、各呼び出しで呼び出し元が常に変更されるとは限りません。前回呼び出し元がない場合、または前の呼び出し元がオフラインになった場合、負荷分散が実行されます選択する。

FailfastClusterInvoker

このクラスターは1回のリモート呼び出しのみを行います。失敗の直後に例外がスローされると、すぐに失敗します。これは、同一性をサポートしない呼び出しに適しています。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

コードからわかるように、ロードバランシングを介して呼び出し元を選択し、呼び出しを開始して、失敗した場合はエラーをスローするのは非常に簡単です。

FailsafeClusterInvoker

このクラスターはフェイルセーフクラスターです。つまり、呼び出しエラーはログにのみ記録され、空の結果が返されます。これは、監査ログへの書き込みなどの操作に適しています。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

ご覧のとおり、コードは非常に単純です。エラーをスローすると、ログに記録され、空の結果が返されます。

FailbackClusterInvoker

このクラスターは、呼び出しが失敗した後に呼び出しを記録し、空の結果をサービスコンシューマーに返し、スケジュールされたタスクを介して失敗した呼び出しを再調整します。

メッセージ通知などのベストエフォートシナリオに適しています。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

多くのコードのように見えますが、ロジックは非常に単純です。

呼び出しが失敗すると、空の結果が返され、それがfailedに追加され、失敗した呼び出しを定期的に呼び出す時間指定タスクがあります。呼び出しが成功した場合は、失敗から呼び出しを削除します。

ForkingClusterInvoker

このクラスターは、実行時にスレッドプールを介してすべての呼び出し元に対して同時呼び出しを行います。サービスプロバイダーが結果を正常に返す限り、doInvokeメソッドはその操作を直ちに終了します。

リアルタイム要件の高い読み取り操作に適しています。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

BroadcastClusterInvoker

このクラスターは、実行時にすべての呼び出し元を1つずつ呼び出し、最後に、呼び出しの1つがエラーをスローしたかどうかを判断し、例外をスローします。

キャッシュやログなどのローカルリソース情報を更新するようにすべてのプロバイダーに通知するのに適しています。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

AbstractClusterInvoker

これは実際には親クラスですが、AvailableClusterは内部的にAbstractClusterInvokerを返します。これは主に複数のレジストリで使用されます。より簡単で、機能する方を使用するだけです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

サマリークラスター

上記のクラスターには多くの実装があり、さまざまなシナリオに適していることがわかります。これは実際には優れた抽象化です。この中間層を追加すると、サービスコンシューマーがクラスター呼び出しの詳細から保護され、さまざまなシナリオでより適切なものを選択できます。成し遂げる。

もちろん、実装をカスタマイズして自分で拡張し、ビジネスに適したリンク呼び出しスキームをカスタマイズすることもできます。

Dubboでの負荷分散

負荷分散は、実際にはハードウェア負荷分散とソフトウェア負荷分散に分けられます。誰もがNginxなどのソフトウェア負荷分散に精通している必要があります。

Dubboには、独自のロードバランシングであるLoadBalanceもあります。前述したように、サービスプロバイダーは通常、クラスターにデプロイされます。このクラスターは、コンシューマーが呼び出す呼び出し元を公開しますが、実際に呼び出されるタイミングを判断する必要があります。具体的には、どのサービスプロバイダーが呼び出されるか、そして負荷分散が現場にあります。

したがって、Dubboの負荷分散は、消費者に電話をかけるのに適したサービスプロバイダーを選択するために使用されます。デフォルトでは、Dubboはさまざまな負荷分散アルゴリズムを提供します。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

一つずつ見ていきましょう。これにはアルゴリズムが含まれますが、効果はほとんどありません。大まかに意味を理解しても大丈夫です。もちろん、すべてを理解するのが最善です。まず、これらの実装クラスの親クラスを見てみましょう。

AbstractLoadBalance

これらの実装クラスはすべて、LoadBalanceインターフェイスを実装し、いくつかの一般的なロジックをカプセル化するこのクラスを継承します。これは、テンプレートメソッドであり、使い慣れたレシピでもあります。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

ロジックは非常に単純です。重みの計算方法を見てみましょう。これは一般的なロジックです。実際には、サービスの予熱用です。キャッシュには予熱があり、JITにも予熱があることがわかっています。サービスへの応答は、サービスを予熱する必要があるということです。

サービスを開始したばかりのときは、次回は負荷を高くしすぎないようにし、ゆっくりとウォームアップして負荷をかける必要があるため、この方法でサービスの実行時間を判断し、サービスの電力を削減します。これは最適化方法です。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

RandomLoadBalance

このアルゴリズムはランダムに重み付けされており、アイデアは実際には非常に単純です。例を挙げましょう。2つのサーバーAとBがあるとします。リクエストの70%をAに、30%をBに送信します。これはその時、私は[0,10)でランダムな数の生成範囲を作る必要があります、この10は7 +3から派生しています。

次に、得られた乱数が[0,7)にある場合は、サーバーAが選択され、[7,10)にある場合は、サーバーBが選択されます。もちろん、ランダム番号が適切に分散されていれば、確率は正しくなります。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

それでは、Dubboがどのように実現されるかを見てみましょう。考えは上記の考えです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

非常に単純であることがわかります。たとえば、ランダム数が5の場合、5-7 <0であるため、Aが選択されます。ランダム数が8の場合、8-7は1より大きく、1-3は0より小さいため、これはBを選んだとき。

これは、Dubboがデフォルトで採用している負荷分散の実装です。

LeastActiveLoadBalance

これは最もアクティブでないロードバランサーです。名前から、呼び出しを行うためのアクティブな呼び出しが最も少ないプロバイダーを選択できます。アクティブな呼び出しが少ないということは、非常に簡単になり、アクティブな番号はすべて0から合計されて要求を行うことができます。アクティブな数は+1であり、1つの要求が処理されるアクティブな数は-1であるため、少数のアクティブなものは、偽装して処理速度を反映できます。

これは実際には最小のアクティブな数のアイデアであり、Dubboはアクティブな数が等しいかどうかを判断するために重みを使用します。この重みは実際にはRandomLoadBalanceの実装と同じです。

コードは投稿しません。簡単に言うと、最初に呼び出し元のリストをトラバースして、アクティブ数が最も少ない呼び出し元を見つけます。同じ最小アクティブ数の呼び出し元が複数ある場合は、これらの呼び出し元の添え字を記録して、重みを追加します。重量選択用。

アクティブな番号が最小の呼び出し元が1つしかない場合は、直接戻ります。

ConsistentHashLoadBalance

これは一貫性のあるハッシュ負荷分散アルゴリズムです。一貫性のあるハッシュはすべての人に馴染みのあるものでなければなりません。一般的な一貫性のあるハッシュアルゴリズムは、ハッシュ値スペースを[0、2 ^ 32-1]に設定することで、Kargerによって提案されています。リング形状。

サーバーのIPおよびその他の情報からハッシュ値を生成し、この値をノードとしてリングに投影します。次に、キーが検索されたら、このキー以上のハッシュ値を持つ最初のノードを時計回りに見つけます。

一般的に、仮想ノードは、データをより分散させ、データがノードを圧倒することを回避するために導入されます。公式Webサイトのグラフを参照してください。

私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散
全体的な実装は難しくありません。これは上記のロジックです。サークルは、treeMapを使用して、tailMapを介して実装され、最初の請求書以上の最初の請求書を検索します。最初の請求書を取得する手順が見つからない場合は、直接割り当てます。 treeMapのfirstEntry。

その場合、Dubboにはデフォルトで160の仮想ノードがあります。全体的なハッシュはメソッドレベルです。つまり、サービスの各メソッドにはConsistentHashSelectorがあり、ハッシュはパラメーター値に従って実行されます。つまり、負荷分散ロジックはパラメーター値によってのみ影響を受けます。 、同じパラメータ値を持つリクエストは、同じサービスプロバイダーに割り当てられます。

まず、一貫性のあるハッシュの実装を見てみましょう。このvirtualInvokersはTreeMapです。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散
次に、一貫性のあるハッシュを介して呼び出し元を取得する方法を見てみましょう。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

RoundRobinLoadBalance

これは加重ラウンドロビン負荷分散です。ラウンドロビンが加重ラウンドロビンであることは誰もが知っています。たとえば、2つのサーバーAとBがあります。ポーリング呼び出しの順序はA、B、A、Bです。 ...、重みが追加された場合、AからBへの重みは3:1であり、現在の呼び出し順序はA、A、A、B、A、A、A、Bです。

重み付けの理由は、個々のサーバーのパフォーマンスが優れているため、さらにポーリングしたいと思います。

しかし、このように、Aが最初の3回要求され、次にBが要求されていることがわかります。それは均等ではありません。たとえば90:80です。最初の90回はAにヒットします。Aはビジー状態で、Bはスペースが不足しています。したがって、平滑化する必要があります。

A、B、A、A、B、Aなど、この種のスムーズな加重ポーリングの方が優れています。簡単に言えば、無秩序にポーリングしています。

Dubboの加重ポーリングは、上記の加重ポーリングを経て、加重ポーリングプロセスをスムーズにしました。

特定のコードは分析されておらず、より複雑です。とにかく、これはこれを意味します。Dubboは、Nginxによって実行されるスムーズな加重ポーリングを指します。

個人的には、これは最初のRandomLoadBalanceに似ていると思います。

それらを連結する

これまでのところ、サービスカタログ、クラスター、負荷分散などが含まれています。誰もがそれらの用途をすでに知っていると思います。次に、Dubboのデフォルトの実装クラスの違いと適用可能なシナリオがあります。これについてシリーズで説明します。いくつかが協力して、クラスターのフォールトトレラントな負荷分散機能を完了します。

最初に公式ウェブサイトでこの写真を見てください、それは非常にはっきりしています、そしてそれから私はそれをもう一度説明するために言葉を使います。
私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

まず、サービスが導入されると、複数のリモートコールがディレクトリに詰め込まれ、次にディレクトリがクラスタを介してカプセル化されます。クラスタは、FailOver、FailFastなどのさまざまな障害耐性機能を提供し、最後に消費者に公開されます。呼び出し元。

次に、消費者が電話をかけると、ディレクトリ内の呼び出し元のリストが取得されます。もちろん、ルーティングによってフィルタリングされます。これらの呼び出し元が取得された後、loadBalanceは負荷分散を実行して呼び出し元を選択し、最後に呼び出しを開始します。

このプロセスは実際にはクラスター内で開始されるため、呼び出しの開始でエラーが発生した場合は、さまざまなフォールトトレラントな手段を使用できます。

やっと

私の妹は私に尋ねました:ダボクラスターの耐障害性の負荷分散

この時点で、Dubboシステム全体に精通しているはずです。前の記事を振り返って統合し、もう一度頭の中で確認できます。このシステム全体は頭の中で確立されており、基本的に安定しています。

フォローアップのダボでは、最後のインタビューの乾物バージョンを最後まで出します。実際、技術的な乾物を書く人は本当に少ないので、ダボを書く時期は非常に絡み合っていますが、それでも書き続けたいと言っています。正直言って、読みたくないと言ってはいけません。私は書くのがとても辛いです。固執するのが難しいこともあります。でも、将来読みたいときは、アオビンが書いたようで、歴史的な記録を見るだけで十分だと思います。アップ。

私は永遠の時間を気にしません、私はそれを一度持ってそれを愛することだけを気にします。私はアオビンです。あなたのサンリアンに感謝します。あなたが知っているほど、あなたはもっと知りません。また会いましょう。

おすすめ

転載: blog.51cto.com/14689292/2545233
おすすめ