Nginxポーリングアルゴリズムの基本的な実装方法の詳細な説明

Nginxポーリングアルゴリズムの基本的な実装方法の詳細な説明

ポーリングアルゴリズムの紹介

多くの人が職場で nginx を使用しており、その設定に精通しています。今日は、nginx ポーリング アルゴリズムの基礎となる実装をいくつか紹介したいと思います。

シンプルなポーリングアルゴリズム

このアルゴリズムは比較的単純です。たとえば、サーバーが 3 台あるとします。

最初のサーバー192.168.1.1
セカンドサーバー192.168.1.2
3番目のサーバー192.168.1.3

最初のリクエストが到着すると、デフォルトで最初のサーバーにアクセスします。2 番目のリクエストは、2 番目のサーバーにアクセスするために到着します。3 番目のリクエストは、3 番目のサーバーにアクセスするために到着します。4 番目のリクエストは、最初のサーバーにアクセスするために到着します。以下は、単純なアルゴリズムを実装するためのコードです。

パブリッククラスSimplePolling {

  /**
   * キーはip
   */
  パブリック静的リスト <String> ipService = 新しい LinkedList <>();
  静的{
    ipService.add("192.168.1.1");
    ipService.add("192.168.1.2");
    ipService.add("192.168.1.3");
  }
  パブリック静的int pos = 0;
  パブリック静的文字列 getIp(){
    if(pos >= ipService.size()){
      //インデックスが範囲外にならないようにする pos = 0;
    }
    文字列 ip = ipService.get(pos);
    位置++;
    IP を返します。

  }

  パブリック静的voidメイン(String[] args) {
    (int i = 0; i < 4; i++) の場合 {
      System.out.println(getIp());

    }
  }
}

シミュレーションは4回実行され、結果は

ここに画像の説明を挿入

このとき、より性能の良いサーバー(192.168.1.1 など)があれば、このサーバーでより多くのリクエストを処理したいと考えています。このとき、重みの確率が関係しており、このアルゴリズムは実装できません。後で説明するポーリング アルゴリズムのアップグレード バージョンを参照してください。

加重ラウンドロビン

このとき、最初の 3 つのサーバーの重みを、最初のサーバーには 5、2 番目のサーバーには 1、3 番目のサーバーには 1 のように設定する必要があります。

最初のサーバー192.168.1.1 5
セカンドサーバー192.168.1.2 1
3番目のサーバー192.168.1.3 1

このとき、最初の 5 つのリクエストは最初のサーバーにアクセスし、6 番目のリクエストは 2 番目のサーバーにアクセスし、7 番目のリクエストは 3 番目のサーバーにアクセスします。

私が示したコード例は次のとおりです。

パブリッククラス WeightPolling {

  /**
   * キーは ip、値は weight*/
  パブリック静的 Map<String, Integer> ipService = new LinkedHashMap<>();
  静的{
    ipService.put("192.168.1.1", 5);
    ipService.put("192.168.1.2", 1);
    ipService.put("192.168.1.3", 1);
  }
  パブリック静的intリクエストId = 0;
  パブリック静的int getAndIncrement() {
    requestId++ を返します。
  }

  パブリック静的文字列 getIp(){
    // 総重量を取得します int totalWeight =0;
    (整数値: ipService.values()) {
      合計重量+=値;
    }
    //現在のポーリング値を取得します int andIncrement = getAndIncrement();
    int pos = andIncrement% totalWeight;
    (文字列ip:ipService.keySet()) {
      ipService.get(ip) が pos より小さい場合
        IP を返します。
      }
      pos -= ipService.get(ip);
    }
    null を返します。
  }

  パブリック静的voidメイン(String[] args) {
    (int i = 0; i < 7; i++) の場合 {
      System.out.println(getIp());
    }
  }

}

今回走った結果は

ここに画像の説明を挿入

最初のサーバーが 5 回実行され、次の 2 つのサーバーが 1 回実行された、というように実行されたことがわかります。おそらく、このアルゴリズムは悪くないと思うでしょう。実は、このアルゴリズムには欠点があります。最初のサーバーの重みを高く設定しすぎると、最初のサーバーに多くのリクエストを実行する必要がある場合があります。この場合、分散が不均一になり、1 つのサーバーに過度の負荷がかかり、クラッシュする可能性があります。そこで、この問題を解決するための 3 番目のアルゴリズムを後で紹介します。

滑らかな重み付けラウンドロビンアルゴリズム

このアルゴリズムは複雑かもしれません。初めて見たときはよくわかりませんでした。関連情報を読んだ後、自分の理解を組み合わせて、画像とテキストで説明しました。ここで例として使用したサーバー構成と重みは上記と同じです。

聞く現在の体重 = 自分の体重 + 選択後の現在の体重総重量現在の最大重量返されたIP選択後、現在の重量 = 現在の最大重量 - 合計重量
1 {5,1,1} 7 5 192.168.1.1 {-2,1,1}
2 {3,2,2} 7 3 192.168.1.1 {-4,2,2}
3 {1,3,3} 7 3 192.168.1.2 {1,-4,3}
4 {6,-3,4} 7 6 192.168.1.1 {-1,-3,4}
5 {4,-2,5} 7 5 192.168.1.3 {4,-2,-2}
6 {9,-1,-1} 7 9 192.168.1.1 {2,-1,-1}
7 {7,0,0} 7 7 192.168.1.1 {0,0,0}

上図から、第 1 サーバーの重みが 5 に設定されているにもかかわらず、5 番目のリクエストが必ずしも第 1 サーバーによって実行されるわけではないことがわかります。代わりに、実行は分散され、スケジューリングのシーケンスは非常に均一です。また、7 回目のスケジューリング後、現在の重みは {0, 0, 0} に戻り、インスタンスの状態は初期状態と一致しているため、その後はスケジューリング操作を繰り返すことができます。

前の図の意味がよく分からない人もいるかもしれないので、ここで簡単に説明します。

1. まず、合計重量は変わりません。デフォルトでは、現在設定されている重量の合計になります。

2. 最初のリクエストが到着すると、現在の重み選択値がデフォルトで {0,0,0} に初期化されるため、現在の重み値は {5+0,1+0,1+0} になります。ここで、5,1,1 は、前に設定した各サーバーの重みセットです。

3. ここで、最初のリクエストの最大重みは 5 であると結論付けることができます。その後、最初のサーバーのIPに戻ります

4. 次に、選択後の現在の重量を設定します。これは、現在の最大重量から合計重量 (5-7) を引いたものです。選択されていない重量は変更されません。この時点で、現在の重量の選択された重量の値は {5-7,1,1} です。

5. 2 番目のリクエストが来たら、上記の手順 2、3、4 を引き続き実行します。

それでもまだ理解できない場合は、以下に Java コードで実装した独自のアルゴリズムを示します。

パブリッククラスポーリング{

  /**
   * キーは ip、値は weight*/
  パブリック静的 Map<String,Integer> ipService = new LinkedHashMap<>();
  静的{
    ipService.put("192.168.1.1",5);
    ipService.put("192.168.1.2",1);
    ipService.put("192.168.1.3",1);
  }
  プライベート静的 Map<String,Weight> weightMap = new LinkedHashMap <>();

  パブリック静的文字列 getIp(){
    // 総重量を計算します int totalWeight = 0;
    (整数値: ipService.values()) {
      合計重量+=値;
    }
    //まずweightMapが空かどうかを判定します。if (weightMap.isEmpty()) {
      ipService.forEach((ip,weight)->{
        重み weights = new Weight(ip, weight,0);
        weightMap.put(ip,weights);
      });
    }
    //マップ内のオブジェクトの現在の重みを設定します weightMap.forEach((ip,weight)->{
      weight.setCurrentWeight(weight.getWeight() + weight.getCurrentWeight());
    });

    // 最大重量が現在の重量より大きいかどうかを判断します。空または現在の重量より小さい場合は、現在の重量を最大重量に割り当てます。 Weight maxWeight = null;
    (重量 weight : weightMap.values()) の場合 {
      if(maxWeight == null || weight.getCurrentWeight() > maxWeight.getCurrentWeight()){
        maxWeight = 重量;
      }
    }
    //最後に、現在の最大重量から合計重量を減算します。maxWeight.setCurrentWeight(maxWeight.getCurrentWeight() - totalWeight);
    //戻り値 maxWeight.getIp();
  }

  パブリック静的voidメイン(String[] args) {
    //IPを取得するために7回のポーリングをシミュレートする
    (int i = 0; i < 7; i++) の場合 {
      System.out.println(getIp());
    }
  }

}

クラス ウェイト{
  /**
   * IPアドレス
   */
  プライベート文字列 ip;
  /**
   * 重量を設定する */
  プライベート int 重み;
  /**
   * 現在の体重 */
  プライベート int 現在の重量;

  パブリックウェイト(文字列ip、intウェイト、int現在のウェイト) {
    ip は ip です。
    this.weight = 重量;
    this.currentWeight = 現在の重量;
  }

  パブリック文字列 getIp() {
    IP を返します。
  }

  パブリック void setIp(String ip) {
    ip は ip です。
  }

  パブリック int getWeight() {
    重量を返します。
  }

  パブリック void setWeight(int 重量) {
    this.weight = 重量;
  }

  パブリック int getCurrentWeight() {
    現在の重量を返します。
  }

  パブリック void setCurrentWeight(int currentWeight) {
    this.currentWeight = 現在の重量;
  }
}

ここでコードを実行した結果は次のようになります。

ここに画像の説明を挿入

ここでの実行結果は、表に記載されている結果と一致していることがわかります。

要約する

3 番目のアルゴリズムは、少し複雑でわかりにくいかもしれません。チャートの意味がわからない場合は、まずコードを実行してください。デバッガーでステップごとにデバッグすると、簡単に理解できます。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Nginx で Brotli 圧縮アルゴリズムを有効にする方法の例
  • Nginx で Brotli アルゴリズム圧縮を有効にする例
  • NginxはGzipアルゴリズムを使用してメッセージを圧縮します
  • Nginx 7層負荷分散のいくつかのスケジューリングアルゴリズムの簡単な理解
  • Nginx の負荷分散アルゴリズムとフェイルオーバー分析
  • C# は Nginx のスムーズな重み付けポーリング アルゴリズムを実装します
  • nginxの4つのスケジューリングアルゴリズムと高度な機能の詳細な分析
  • Brotli圧縮アルゴリズムを有効にするNginxの実装プロセスの詳細な説明

<<:  CentOS に Redis と MySQL をインストールする

>>:  WeChatアプレットがジグソーパズルゲームを実装

推薦する

Windows Server 2008 R2 リモート デスクトップのポート 3389 を変更する方法

Windows サーバー リモート デスクトップのデフォルトのポート番号は 3389 です。職場でサ...

Linux における nohup と & の使い方と違いの詳細な説明

例:例として、Python コード loop_hello.py を使用します。このコードは、ループ回...

MySQLデータベースの増分バックアップのアイデアと方法

MySQL データベースの増分バックアップを実行するには、データベース構成ファイル /etc/my....

Alibaba Cloud ECS centos6.8 に MySql5.7 をインストールして設定するチュートリアル

Alibaba Cloud yum コマンドでのデフォルトの MySQL バージョンは 5.17**...

シームレスなカルーセル効果を実現するネイティブ js

参考までに、ネイティブjsでカルーセル効果(シームレススクロール)を実現しています。具体的な内容は以...

Tomcat が https アクセスをサポートするための手順の説明

tomcat を https アクセスに対応させる方法ステップ: (1)キーストアファイルを生成する...

Ubuntu 20.04にvncserverをインストールする方法

Ubuntu 20.04は2020年4月に正式にリリースされました。本日、ミラーシステムを正式にイン...

MySQLデータベースパラダイムの詳細な説明

序文:データベースパラダイムについてはよく耳にしていましたが、詳細まで理解したことはありませんでした...

Mysql での結合操作

結合の種類1. 内部結合: 結合関係を持つ 2 つのテーブル内のフィールドは、結合関係を満たすレコー...

Nexus をベースに Alibaba Cloud プロキシ ウェアハウスを構成するプロセスの分析

Nexus のデフォルトのリモートリポジトリは https://repo1.maven.org/ma...

vue3.0+echarts は 3 次元の縦棒グラフを実現します

序文: Vue3.0はechartsの3次元縦棒グラフを実装します結果: 実装手順: 1. echa...

Tomcat マルチレイヤーコンテナの設計に関する簡単な説明

目次コンテナ階層サーブレットの検索を要求するプロセス仕組みTomcat のコンテナは Servlet...

新しい Linux ファイル権限設定における umask の詳細な理解

序文起源は質問 1 です: umask が 022 に設定されている場合、作成するファイルのデフォル...

CSS グラデーション効果の概要 (線形グラデーションと放射状グラデーション)

線形グラデーション 背景画像: linear-gradient(方向、開始色、中間色1、中間色2、....

水平ヒストグラムを作成するための MySQL ソリューション

序文ヒストグラムは、RDBMS によって提供される基本的な統計情報です。最も一般的に使用されるのは、...