ポーリングアルゴリズムの紹介 多くの人が職場で 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 を応援していただければ幸いです。
<<: CentOS に Redis と MySQL をインストールする
この記事は主に、nginx を介して方向プロキシを実装するプロセスを紹介します。この記事のサンプル ...
ウェブサイトでは、コンテンツの(100-1)%がナビゲーションです1. ジェシー・ジェームズ・ギャレ...
どの要素でもスクロールできるようにしながら、スクロールバーを非表示にするにはどうすればよいでしょうか...
この記事では、MySQL 5.7.27 winx64のインストールと設定方法を参考までに紹介します。...
目次序文1. 再帰コンポーネント2. 右クリックメニューコンポーネント要約する序文今日、プロジェクト...
美しい HTML コードの外観 美しい HTML コードの書き方。外国人が書いた記事: 美しい HT...
<br />元のアドレス: http://andymao.com/andy/post/8...
カルーセルアニメーションは、ページの外観とインタラクティブなパフォーマンスを向上させることができます...
Apollo オープンソース アドレス: https://github.com/ctripcorp/...
目次1. 関数の定義1.1 JavaScript の関数1.2 TypeScriptの関数2. オプ...
基本的にすべてのeコマースプロジェクトにはショッピングカートの機能があります。これはreact-na...
序文公式アカウントのQRコードは長押しで認識できることは皆さんご存じですが、ミニプログラムに対する制...
まず、Docker とは何かを理解しましょう。 Docker は、アプリケーションをデプロイするため...
非同期レプリケーションMySQL レプリケーションは、デフォルトでは非同期です。マスター スレーブ ...
この記事では、例を使用して、MySQL の日付と時刻の間隔計算について説明します。ご参考までに、詳細...