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コードからフォローできます。この記事を転載する場合は、メロン農家ラオリャンの公開アカウントまでご連絡ください。

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

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

ブログ    
ブログ    
ブログ    

推薦する

自動運転がどんどん近づき、高精度地図の実用化も加速

近年、自動運転技術の急速な発展とインテリジェントコネクテッドカーの導入が進む中、鍵となる高精度地図の...

私の国のロボット市場は活況を呈しているが、人材と技術的な問題はまだ解決する必要がある。

「スマート+」時代の到来とともに、人工知能、5G、モノのインターネット、ビッグデータなどの技術が徐...

2025年以降の人工知能の未来(パート1)

[[420733]] 2025 年までに、人工知能 (AI) は、今日の複雑なタスクの一部を効率的...

自律飛行ロボットが浙江大学から集団で飛び立ち、サイエンス誌の表紙に登場

最近、浙江省安吉市の竹林で、一群の超小型知能ドローンが集団で派遣され、ジャングルの中を楽々と移動した...

AIがマーケティングオーディエンスの洞察をどのように変えるのか

[[429813]]人工知能は、企業のマーケティング範囲の拡大に大きく貢献することが証明されています...

...

海外の専門家による人工知能の発展見通しに関する衝撃的な4つの予測

[[240152]]人工知能技術が成熟するにつれ、この技術のより広範な社会的、倫理的影響に十分な注意...

...

東南大学が世界初のLK-99ゼロ耐性テストに成功しました!常温超伝導が再び出現、人類史は転換点に近づいている

室温超伝導を再現する実験は、完全に爆発的な成長期に突入しました!今朝午前1時過ぎ、東南大学の物理学教...

認知知能を業界の奥深くまで導くWAIC Baiduが言語と知識技術の完全なレイアウトを公開

言語は機械と人間をつなぐ重要な経路であり、機械が現実世界を深く理解するためには知識が必要です。 8月...

AI時代の南北格差を埋める

[[427918]]周其浦松陽人工知能(AI)の発展は世界に変革をもたらしましたが、同時に発展途上国...

Uber劉延東:Uberがフードデリバリーサービスを開始したとき、世界中のフードデリバリー会社は衝撃を受けた

[ 51CTO.comより引用 ] 2017年7月21日から22日まで、51CTOが主催する人工知能...

AIOps で IT 運用にインテリジェンスを組み込む方法

クラウド プラットフォーム、マネージド サービス プロバイダー、デジタル変革を進めている組織は、AI...

...