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アプレットがジグソーパズルゲームを実装

推薦する

HTMLの基礎を詳しく解説(第2部)

1. リストリスト ulコンテナーには、一貫した構造とスタイルを持つテキストまたはグラフの形式が読...

Windows Apache 環境で SSL 証明書を展開して、Web サイトを https 対応にする方法

SSL 証明書の使用についてはここでは説明しません。SSL 証明書を導入する必要がある友人は、すでに...

MySQL での一時テーブルの使用例

ここ2日間ちょっと忙しくて、公式アカウントも数日更新が止まってしまいました。その結果、何人かの読者か...

Vue で棒グラフを使用し、自分で設定を変更する方法

1. HTMLファイルでechartをインポートする <!-- echarts をインポート ...

bodyタグの主な属性の概要

bgcolor="テキストの色" background="背景画像&q...

jsはブラウザを閉じるときにアカウントのログアウトを処理します

目次古典的なアプローチ質問その他の質問注意が必要な問題古典的なアプローチご存知のとおり、アカウントの...

DockerはGitを使用してJenkinsのリリースとテストプロジェクトの詳細なプロセスを実装します

目次1. Dockerをインストールする2. カスタムネットワークアドレスを作成する3. Docke...

Node.js の非同期イテレータの詳細な説明

目次序文非同期イテレータとは何ですか?非同期イテレータストリームとしてページング機能を備えたAPIの...

時間のかかるMySQLレコードのSQL例の詳細な説明

mysqlは時間のかかるSQLを記録しますMySQL は、最適化と分析のために、時間のかかる SQL...

HTML でスクロールバーを使用する際のヒントを共有する

今日、牛南ニュースリリースシステムについて学んでいたとき、牛南先生はスクロールバーに関するいくつかの...

nginxサーバーのダウンロード、インストール、使用方法の詳細な説明

ダウンロードhttp://nginx.org/en/download.html解凍ダウンロードしたn...

初心者がHTMLタグを学ぶ(2)

初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...

Vue router-viewとrouter-linkの実装原理

使用 <div id="アプリ"> <router-link ...

CSS3 3Dクールキューブ変形アニメーションの実装

私はコーディングが大好きです。コーディングすると幸せになります!みなさんこんにちは、Counterで...

異なる列を持つテーブルのクエリ結果のSQLマージ操作

2 つの異なるテーブルをクエリするには、結果をマージする必要があります。たとえば、table1 の列...