簡單輪詢演算法
這種演算法比較簡單,舉例就是你有三台伺服器
第一台伺服器 | 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次執行結果是
此時如果我有一台伺服器效能比較好(例如192.168.1.1),我想讓這台伺服器處理多一點請求,此時就涉及到了權重得概率,這種演算法就不能實現,請看我後面描述的輪詢升級版演算法。
加權輪詢演算法
此時我需要把我前面3台伺服器都設定權重,例如第一台設定5,第二台設定1,第三台設定1
第一台伺服器 | 192.168.1.1 | 5 |
#第二台伺服器 | 192.168.1.2 | 1 |
第三台伺服器 | 192.168.1.3 | 1 |
此時前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()); } } }
此時執行結果是
可以看的第一台伺服器執行了5次,後面2台依序執行一次,依序類推。可能你覺得這種演算法還不錯。其實這種演算法有一個缺點是,如果我第一台伺服器設定權重過大可能我需要很多次請求都執行到第一台伺服器上去,這樣的情況分佈是不均勻的,會造成某一台伺服器壓力過大導致崩潰。所以我後面要引入第三種演算法來解決這個問題
平滑加權輪詢演算法
這個演算法可能比較複雜,我第一次看也有點不太明白,後面看過相關資料在結合我自己的理解給大家圖文解釋一下,這裡我舉例的伺服器配置和權重還是跟上面一樣
請求 | 目前權重= 自身權重選中後目前權重 | 總權重 | #目前最大權重 | 傳回的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} | |
##{4,-2,5} | #7 | 5 | 192.168.1.3 | #{4,-2,-2} | ##6 |
7 | 9 | #192.168.1.1 | {2,-1,-1} | 7 | |
7 | 7 | 192.168.1.1 | {0,0,0} |
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如何實作輪詢演算法的詳細內容。更多資訊請關注PHP中文網其他相關文章!