首頁 > 運維 > Nginx > Nginx如何實作輪詢演算法

Nginx如何實作輪詢演算法

WBOY
發布: 2023-05-21 21:43:13
轉載
1633 人瀏覽過

簡單輪詢演算法

這種演算法比較簡單,舉例就是你有三台伺服器

第一台伺服器 192.168.1.1
#第二台伺服器 192.168.1.2
#第三台伺服器 192.168.1.3

#第一個請求過來之後預設存取第一台,第二個請求過來存取第二台,第三次請求過來訪問第三台,第四次請求過來訪問第一台,以此類推。以下是我程式碼實作簡單得演算法:

public class simplepolling {

  /**
   * key是ip
   */
  public static list <string> ipservice = new linkedlist <>();
  static {
    ipservice.add("192.168.1.1");
    ipservice.add("192.168.1.2");
    ipservice.add("192.168.1.3");
  }
  public static int pos = 0;
  public static string getip(){
    if(pos >= ipservice.size()){
      //防止索引越界
      pos = 0;
    }
    string ip = ipservice.get(pos);
    pos ++;
    return ip;

  }

  public static void main(string[] args) {
    for (int i = 0; i < 4; i++) {
      system.out.println(getip());

    }
  }
}
登入後複製

模擬執行4次執行結果是

Nginx如何實作輪詢演算法

此時如果我有一台伺服器效能比較好(例如192.168.1.1),我想讓這台伺服器處理多一點請求,此時就涉及到了權重得概率,這種演算法就不能實現,請看我後面描述的輪詢升級版演算法。

加權輪詢演算法

此時我需要把我前面3台伺服器都設定權重,例如第一台設定5,第二台設定1,第三台設定1

第一台伺服器192.168.1.15
#第二台伺服器192.168.1.21
第三台伺服器192.168.1.31

此時前5個請求都會存取到第一台伺服器,第六個請求會存取到第二台伺服器,第七個請求會訪問到第三台伺服器。

以下是我給的程式碼案例:

public class weightpolling {

  /**
   * key是ip,value是权重
   */
  public static map<string, integer> ipservice = new linkedhashmap<>();
  static {
    ipservice.put("192.168.1.1", 5);
    ipservice.put("192.168.1.2", 1);
    ipservice.put("192.168.1.3", 1);
  }
  public static int requestid = 0;
  public static int getandincrement() {
    return requestid++;
  }

  public static string getip(){
    //获取总的权重
    int totalweight =0;
    for (integer value : ipservice.values()) {
      totalweight+= value;
    }
    //获取当前轮询的值
    int andincrement = getandincrement();
    int pos = andincrement% totalweight;
    for (string ip : ipservice.keyset()) {
      if(pos < ipservice.get(ip)){
        return ip;
      }
      pos -= ipservice.get(ip);
    }
    return null;
  }

  public static void main(string[] args) {
    for (int i = 0; i < 7; i++) {
      system.out.println(getip());
    }
  }

}
登入後複製

此時執行結果是

Nginx如何實作輪詢演算法

可以看的第一台伺服器執行了5次,後面2台依序執行一次,依序類推。可能你覺得這種演算法還不錯。其實這種演算法有一個缺點是,如果我第一台伺服器設定權重過大可能我需要很多次請求都執行到第一台伺服器上去,這樣的情況分佈是不均勻的,會造成某一台伺服器壓力過大導致崩潰。所以我後面要引入第三種演算法來解決這個問題

平滑加權輪詢演算法

這個演算法可能比較複雜,我第一次看也有點不太明白,後面看過相關資料在結合我自己的理解給大家圖文解釋一下,這裡我舉例的伺服器配置和權重還是跟上面一樣

##6# 192.168.1.1{-1,-3,4}#5##6#{9,-1,-1}79#192.168.1.1{2,-1,-1}7{7,0,0}77192.168.1.1{0,0,0}由上圖可以看出第一台伺服器雖然權重設定的是5,但不是第五次請求過來都是第一台伺服器執行,而是分散執行,調度序列是非常均勻的,且第7 次調度時選中後當前權重又回到{0, 0, 0},實例的狀態同初始狀態一致,所以後續可以一直重複調度操作。
請求目前權重= 自身權重選中後目前權重總權重#目前最大權重傳回的ip選取後當前權重=目前最大權重-總權重
1{5,1,1}#7 5192.168.1.1{-2,1,1}
2{3,2 ,2}73192.168.1.1{-4,2,2}
3{1,3,3}73192.168.1.2{1,-4 ,3}
4{6,-3,4}7
##{4,-2,5} #75192.168.1.3#{4,-2,-2}
可能有的人還不能清楚的明白上一張圖表示的含義,我這裡大概描述一下:

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,3,4步驟執行.

如果這裡還有不懂我下面會提供我自己用java程式碼實作的演算法:

public class polling {

  /**
   * key是ip,value是权重
   */
  public static map <string,integer> ipservice = new linkedhashmap <>();
  static {
    ipservice.put("192.168.1.1",5);
    ipservice.put("192.168.1.2",1);
    ipservice.put("192.168.1.3",1);
  }
  private static map<string,weight> weightmap = new linkedhashmap <>();

  public static string getip(){
    //计算总的权重
     int totalweight = 0;
    for (integer value : ipservice.values()) {
      totalweight+=value;
    }
    //首先判断weightmap是否为空
    if(weightmap.isempty()){
      ipservice.foreach((ip,weight)->{
        weight weights = new weight(ip, weight,0);
        weightmap.put(ip,weights);
      });
    }
    //给map中得对象设置当前权重
    weightmap.foreach((ip,weight)->{
      weight.setcurrentweight(weight.getweight() + weight.getcurrentweight());
    });

    //判断最大权重是否大于当前权重,如果为空或者小于当前权重,则把当前权重赋值给最大权重
    weight maxweight = null;
    for (weight weight : weightmap.values()) {
      if(maxweight ==null || weight.getcurrentweight() > maxweight.getcurrentweight()){
        maxweight = weight;
      }
    }
    //最后把当前最大权重减去总的权重
    maxweight.setcurrentweight(maxweight.getcurrentweight() - totalweight);
    //返回
    return maxweight.getip();
  }

  public static void main(string[] args) {
    //模拟轮询7次取ip
    for (int i = 0; i < 7; i++) {
      system.out.println(getip());
    }
  }

}

class weight{
  /**
   * ip
   */
  private string ip;
  /**
   * 设置得权重
   */
  private int weight;
  /**
   * 当前权重
   */
  private int currentweight;

  public weight(string ip, int weight,int currentweight) {
    this.ip = ip;
    this.weight = weight;
    this.currentweight = currentweight;
  }

  public string getip() {
    return ip;
  }

  public void setip(string ip) {
    this.ip = ip;
  }

  public int getweight() {
    return weight;
  }

  public void setweight(int weight) {
    this.weight = weight;
  }

  public int getcurrentweight() {
    return currentweight;
  }

  public void setcurrentweight(int currentweight) {
    this.currentweight = currentweight;
  }
}
登入後複製
這裡程式碼得執行結果是:


可以看出此處執行結果和表格裡描述得結果一致。 Nginx如何實作輪詢演算法

以上是Nginx如何實作輪詢演算法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板