Nacos ランダムウェイト負荷分散アルゴリズム

Nacos ランダムウェイト負荷分散アルゴリズム

導入

Nacos は、クライアントがノードを選択するときに重みベースのランダム アルゴリズムを提供します。ソース コードを分析することで、その実装原理を理解し、実際の戦闘で使用することができます。

1. 要約

次の図は、ランダム ウェイト負荷分散アルゴリズムのプロセスを示しています。

ノードリスト

5 つのノードが登録されており、各ノードの重みが次のようになっているとします。

増加する配列の整理

目的は重み配列を形成することです。重み配列の要素は[0〜1]の範囲の値を取り、要素は1つずつ増加します。計算プロセスを下の図に示します。また、不健全なノードや重みが 0 以下のノードは選択されないことに注意してください。

ランダム化アルゴリズム

[0~1]の範囲で乱数を生成し、バイナリサーチを使用して増加する配列weights[]に近いインデックスを見つけ、登録されたノードリストからノードを返します。

2. ソースコード分析

ランダムウェイト負荷分散アルゴリズムは、NacosNamingService#selectOneHealthyInstance で提供されています。一緒に確認してみましょう。

  1. @オーバーライド
  2. パブリックインスタンス selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe)
  3. NacosException をスローします {
  4. selectOneHealthyInstance(serviceName、groupName、新しいArrayList<String>()、subscribe)を返します
  5. }
  1. @オーバーライド
  2. パブリックインスタンス selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters,
  3. ブール型subscribe)はNacosExceptionをスローします{
  4. 文字列 clusterString = StringUtils.join (clusters, ", " );
  5. // 注釈 @1
  6. (購読)の場合{
  7. サービス情報 serviceInfo = serviceInfoHolder.getServiceInfo(サービス名、グループ名、クラスター文字列);
  8. if ( null == サービス情報 ) {
  9. serviceInfo = clientProxy.subscribe(サービス名、グループ名、クラスター文字列);
  10. }
  11. Balancer.RandomByWeight.selectHost(serviceInfo)を返します
  12. }それ以外{
  13. // 注釈 @2
  14. サービス情報サービス情報 = clientProxy
  15. .queryInstancesOfService(サービス名、グループ名、クラスター文字列、0、 false );
  16. Balancer.RandomByWeight.selectHost(serviceInfo)を返します
  17. }
  18. }

注: @1 は「キャッシュから登録済みノードのリストを取得する」にサブスクライブしており、デフォルトのサブスクライブは true です。

注 @2 「サーバーから登録ノードのリストを取得する」より

  1. 保護された静的インスタンス getHostByRandomWeight(List<Instance> ホスト) {
  2. NAMING_LOGGER.debug( "エントリ randomWithWeight" );
  3. (ホスト== null || hosts.size () == 0)の場合{
  4. NAMING_LOGGER.debug( "hosts == null || hosts.size() == 0" );
  5. 戻る ヌル;
  6. }
  7. NAMING_LOGGER.debug( "新しいセレクター" );
  8. List<Pair<Instance>> hostsWithWeight = new ArrayList<Pair<Instance>>();
  9. for (インスタンスホスト: hosts) {
  10. if (host.isHealthy()) { // 注釈 @3
  11. hostsWithWeight.add (新しいペア<Instance>(host, host.getWeight()));
  12. }
  13. }
  14. NAMING_LOGGER.debug( "for (ホスト host : hosts)" );
  15. Chooser<String, Instance> vipChooser = new Chooser<String, Instance>( "www.taobao.com" );
  16. // 注釈 @4
  17. vipChooser.refresh(ホストの重みをリフレッシュ)。
  18. NAMING_LOGGER.debug( "vipChooser.refresh" );
  19. // 注釈 @5
  20. vipChooser.randomWithWeight()を返します
  21. }

注 @3 不健全なノードは選択されず、健全なノードの重みとホスト情報を含むペアのリストが作成されます。

注 @4 必要なデータを更新します。これには、すべての正常なノードの重みの合計、各正常なノードの重み比の計算、増分配列の整理という 3 つの部分が含まれます。

  1. パブリックボイドリフレッシュ() {
  2. ダブルオリジンウェイト合計 = (ダブル) 0;
  3. // 注釈@4.1
  4. (ペア<T>アイテム:アイテムの重量) {
  5.  
  6. ダブルウェイト = item.weight();
  7. // 重みゼロのアイテムは無視します。ChooserTesttest_randomWithWeight_weight0を参照してください。
  8. // 0以下の重みは削除されます
  9. (重み<= 0)の場合{
  10. 続く;
  11. }
  12.  
  13. アイテムを追加します(item.item());
  14.  
  15. // 値が無限大の場合
  16. if ( Double .isInfinite(weight)) {
  17. 重量 = 10000.0D;
  18. }
  19.  
  20. // 値が数値以外の値の場合
  21. if ( Double .isNaN(重み)) {
  22. 重量 = 1.0D;
  23. }
  24.  
  25. // 重みの合計を累積する
  26. originWeightSum += 重量;
  27. }
  28.  
  29. // 注釈@4.2
  30. double [] exactWeights = 新しいdouble [items.size ( )];
  31. 整数 インデックス= 0;
  32. (ペア<T>アイテム:アイテムの重量) {
  33. ダブルシングルウェイト = item.weight();
  34. // 重みゼロのアイテムは無視します。ChooserTesttest_randomWithWeight_weight0を参照してください。
  35. シングルウェイト <= 0 の場合
  36. 続く;
  37. }
  38. // 各ノードの重み
  39. exactWeights[インデックス++] = singleWeight / originWeightSum;
  40. }
  41.  
  42. // 注釈@4.3
  43. 重み = 新しいdouble [items.size ( )];
  44. ダブルランダム範囲 = 0D;
  45. ( int i = 0; i <インデックス; i++) {
  46. 重み[i] = ランダム範囲 + exactWeights[i];
  47. ランダム範囲 += exactWeights[i];
  48. }
  49.    
  50. ダブルダブル精度デルタ = 0.0001;
  51.  
  52. if (インデックス== 0 || (Math.abs (重み[インデックス- 1] - 1) < doublePrecisionDelta)) {
  53. 戻る;
  54. }
  55. 新しいIllegalStateExceptionをスローします(
  56. 「累積重みの計算が間違っています。確率の合計が 1 になりません。」 );
  57. }

注 @4.1 すべての健全なノードの重みの合計 originWeightSum

注@4.2 各健全ノードの重み比のexactWeights配列を計算する

注@4.3 増加する配列の重みを整理します。各要素の値は配列内の前の要素の合計です。

このプロセスを説明するために例を見てみましょう。5 つのノードがあるとします。

  1. 1.2.3.4 100
  2. 1.2.3.5 100
  3. 1.2.3.6 100
  4. 1.2.3.7 80
  5. 1.2.3.8 60

ステップ1: ノードの重みの合計を計算する

  • 原点重量合計 = 100 + 100 + 100 + 80 + 60 = 440

ステップ2: 各ノードの重みを計算する

  • 正確な重み[0] = 0.2272
  • 正確な重み[1] = 0.2272
  • 正確な重み[2] = 0.2272
  • 正確な重み[3] = 0.1818
  • 正確な重み[4] = 0.1363

ステップ3: 増加する配列の重みを整理する

  • 重み[0] = 0.2272
  • 重み[1] = 0.4544
  • 重み[2] = 0.6816
  • 重み[3] = 0.8634
  • 重み[4] = 1

注 @5 ランダムに 1 つを選択します。ロジックは次のとおりです。

  1. パブリックTランダムウェイト() {
  2. Ref<T> ref = this.ref;
  3. // 注釈@5.1
  4. ダブルランダム = ThreadLocalRandom.current(). nextDouble (0, 1);
  5. // 注釈@5.2
  6. 整数 インデックス= Arrays.binarySearch(ref.weights, ランダム);
  7. // 注釈@5.3
  8. インデックス<0)の場合{
  9. インデックス= -インデックス- 1;
  10. }それ以外{
  11. // 注釈@5.4
  12. ref.items.get(インデックス)を返します
  13. }
  14.  
  15. // 選択された要素を返す
  16. if (インデックス>= 0 &&インデックス< ref.weights.length) {
  17. if (random < ref.weights[インデックス]) {
  18. ref.items.get(インデックス)を返します
  19. }
  20. }
  21.  
  22. /* これは決して起こらないはずのことですが、正しい値を返すことを保証します
  23. * オブジェクト ケースある 浮動小数点の不等式の問題
  24. * 累積確率に関して。 */
  25. ref.items.get(ref.items.size ( )-1)を返します
  26. }

注@5.1 0から1の間の乱数を生成する

注@5.2 配列内の近い値のバイナリ検索

注 @5.3 ヒットが見つからない場合は、配列に挿入するための理想的なインデックス値が返されます。

注@5.4 選択したノードを直接クリックすると、

概要: 重みベースのランダム アルゴリズムの実装プロセスは、一見すると複雑ではありません。

この記事はWeChat公式アカウント「Guan Nong Lao Liang」から転載したものです。下のQRコードからフォローできます。この記事を転載する場合は、メロン農家ラオリャンの公開アカウントまでご連絡ください。

<<:  バックトラッキングアルゴリズム - ロボットの動作範囲

>>:  人工知能は人間に取って代わろうとしているのでしょうか、あるいは人間を支配しようとしているのでしょうか?本当にそうなのでしょうか?

ブログ    
ブログ    
ブログ    

推薦する

...

脳のようなデバイスを使用して神経信号を効率的に処理し、新しい脳コンピューターインターフェースを構築する

最近、清華大学マイクロナノエレクトロニクス学部および未来チップ技術先進イノベーションセンターのQia...

Zooxロボットタクシーが半プライベートルートでテストを開始

Zooxの共同創業者兼CTOのジェシー・レビンソン氏によると、同社は数十台のカスタム電動ロボットタク...

Go言語で遺伝的アルゴリズムを実装する方法

ただの楽しみのために、Go 言語を学ぶことにしました。新しい言語を学ぶ最良の方法は、深く学び、できる...

...

...

チューリング賞受賞者のヨシュア・ベンジオ氏:ディープラーニングの最優先事項は因果関係を理解すること

ディープラーニングは大量のデータからパターンを見つけるのが得意だが、それらの間のつながりを説明するこ...

ソラ爆発的人気の裏側|世界のモデルとは何かを語ろう!

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

虐殺後に行方不明になった親族をAIで探す! Googleのエンジニアが第二次世界大戦の70万枚以上の古い写真を識別できる顔認識プログラムを開発

AI顔認識の分野で新たなビジネスが開拓されているのでしょうか?今回の課題は、第二次世界大戦の古い写真...

人間の介入によってモデルのパフォーマンスをどのように向上できるでしょうか?この記事を読んでみてください

金融業界など、一部の業界は誤検知に非常に敏感です。クレジットカード詐欺を検出する際に、検出システムが...

...

...

中国の人工知能都市競争で最も速いのはどの都市でしょうか?

産業発展状況の分析特許出願件数世界第1位[[332768]]我が国は、新たな科学技術革命と産業変革の...

...

ニッチから人気へ: 世界的な AI イノベーションが「ソフト」になった理由

この人工知能の波が出現したとき、世界中の AI 研究所が競争を重視していたことを今でも覚えています。...