亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

幾種簡單的負載均衡算法及其Java代碼實現

2019-11-11 03:53:20
字體:
來源:轉載
供稿:網友

什么是負載均衡

負載均衡,英文名稱為Load Balance,指由多臺服務器以對稱的方式組成一個服務器集合,每臺服務器都具有等價的地位,都可以單獨對外提供服務而無須其他服務器的輔助。通過某種負載分擔技術,將外部發送來的請求均勻分配到對稱結構中的某一臺服務器上,而接收到請求的服務器獨立地回應客戶的請求。負載均衡能夠平均分配客戶請求到服務器陣列,借此提供快速獲取重要數據,解決大量并發訪問服務問題,這種集群技術可以用最少的投資獲得接近于大型主機的性能。

負載均衡分為軟件負載均衡和硬件負載均衡,前者的代表是阿里章文嵩博士研發的LVS,后者則是均衡服務器比如F5,當然這只是提一下,不是重點。

本文講述的是"將外部發送來的請求均勻分配到對稱結構中的某一臺服務器上"的各種算法,并以java代碼演示每種算法的具體實現,OK,下面進入正題,在進入正題前,先寫一個類來模擬ip列表:

public class IpMap   {       // 待路由的Ip列表,Key代表Ip,Value代表該Ip的權重       public static HashMap<String, Integer> serverWeightMap =                new HashMap<String, Integer>();       static       {           serverWeightMap.put("192.168.1.100", 1);           serverWeightMap.put("192.168.1.101", 1);           // 權重為4           serverWeightMap.put("192.168.1.102", 4);           serverWeightMap.put("192.168.1.103", 1);           serverWeightMap.put("192.168.1.104", 1);           // 權重為3           serverWeightMap.put("192.168.1.105", 3);           serverWeightMap.put("192.168.1.106", 1);           // 權重為2           serverWeightMap.put("192.168.1.107", 2);           serverWeightMap.put("192.168.1.108", 1);           serverWeightMap.put("192.168.1.109", 1);           serverWeightMap.put("192.168.1.110", 1);       }   }

 輪詢(Round Robin)法

輪詢法即Round Robin法,其代碼實現大致如下:

public class RoundRobin   {       PRivate static Integer pos = 0;       public static String getServer()       {           // 重建一個Map,避免服務器的上下線導致的并發問題           Map<String, Integer> serverMap =                    new HashMap<String, Integer>();           serverMap.putAll(IpMap.serverWeightMap);           // 取得Ip地址List           Set<String> keySet = serverMap.keySet();           ArrayList<String> keyList = new ArrayList<String>();           keyList.addAll(keySet);           String server = null;           synchronized (pos)           {               if (pos > keySet.size())                   pos = 0;               server = keyList.get(pos);               pos ++;           }           return server;       }   }

由于serverWeightMap中的地址列表是動態的,隨時可能有機器上線、下線或者宕機,因此為了避免可能出現的并發問題,方法內部要新建局部變量serverMap,現將serverMap中的內容復制到線程本地,以避免被多個線程修改。這樣可能會引入新的問題,復制以后serverWeightMap的修改無法反映給serverMap,也就是說這一輪選擇服務器的過程中,新增服務器或者下線服務器,負載均衡算法將無法獲知。新增無所謂,如果有服務器下線或者宕機,那么可能會訪問到不存在的地址。因此,服務調用端需要有相應的容錯處理,比如重新發起一次server選擇并調用。

對于當前輪詢的位置變量pos,為了保證服務器選擇的順序性,需要在操作時對其加鎖,使得同一時刻只能有一個線程可以修改pos的值,否則當pos變量被并發修改,則無法保證服務器選擇的順序性,甚至有可能導致keyList數組越界。

輪詢法的優點在于:試圖做到請求轉移的絕對均衡。

輪詢法的缺點在于:為了做到請求轉移的絕對均衡,必須付出相當大的代價,因為為了保證pos變量修改的互斥性,需要引入重量級的悲觀鎖synchronized,這將會導致該段輪詢代碼的并發吞吐量發生明顯的下降。

 

隨機(Random)法

通過系統隨機函數,根據后端服務器列表的大小值來隨機選擇其中一臺進行訪問。由概率統計理論可以得知,隨著調用量的增大,其實際效果越來越接近于平均分配流量到每一臺后端服務器,也就是輪詢的效果。

隨機法的代碼實現大致如下:

public class Random   {       public static String getServer()       {           // 重建一個Map,避免服務器的上下線導致的并發問題           Map<String, Integer> serverMap =                    new HashMap<String, Integer>();           serverMap.putAll(IpMap.serverWeightMap);           // 取得Ip地址List           Set<String> keySet = serverMap.keySet();           ArrayList<String> keyList = new ArrayList<String>();           keyList.addAll(keySet);           java.util.Random random = new java.util.Random();           int randomPos = random.nextInt(keyList.size());           return keyList.get(randomPos);       }   }

整體代碼思路和輪詢法一致,先重建serverMap,再獲取到server列表。在選取server的時候,通過Random的nextInt方法取0~keyList.size()區間的一個隨機值,從而從服務器列表中隨機獲取到一臺服務器地址進行返回?;诟怕式y計的理論,吞吐量越大,隨機算法的效果越接近于輪詢算法的效果。

 

源地址哈希(Hash)法

源地址哈希的思想是獲取客戶端訪問的IP地址值,通過哈希函數計算得到一個數值,用該數值對服務器列表的大小進行取模運算,得到的結果便是要訪問的服務器的序號。源地址哈希算法的代碼實現大致如下:

public class Hash      {          public static String getServer()          {              // 重建一個Map,避免服務器的上下線導致的并發問題              Map<String, Integer> serverMap =                       new HashMap<String, Integer>();              serverMap.putAll(IpMap.serverWeightMap);              // 取得Ip地址List              Set<String> keySet = serverMap.keySet();              ArrayList<String> keyList = new ArrayList<String>();              keyList.addAll(keySet);              // 在Web應用中可通過HttpServlet的getRemoteIp方法獲取              String remoteIp = "127.0.0.1";              int hashCode = remoteIp.hashCode();              int serverListSize = keyList.size();              int serverPos = hashCode % serverListSize;              return keyList.get(serverPos);          }      }

前兩部分和輪詢法、隨機法一樣就不說了,差別在于路由選擇部分。通過客戶端的ip也就是remoteIp,取得它的Hash值,對服務器列表的大小取模,結果便是選用的服務器在服務器列表中的索引值。

源地址哈希法的優點在于:保證了相同客戶端IP地址將會被哈希到同一臺后端服務器,直到后端服務器列表變更。根據此特性可以在服務消費者與服務提供者之間建立有狀態的session會話。

源地址哈希算法的缺點在于:除非集群中服務器的非常穩定,基本不會上下線,否則一旦有服務器上線、下線,那么通過源地址哈希算法路由到的服務器是服務器上線、下線前路由到的服務器的概率非常低,如果是session則取不到session,如果是緩存則可能引發"雪崩"。如果這么解釋不適合明白,可以看我之前的一篇文章MemCache超詳細解讀,一致性Hash算法部分。

 

加權輪詢(Weight Round Robin)法

不同的服務器可能機器配置和當前系統的負載并不相同,因此它們的抗壓能力也不盡相同,給配置高、負載低的機器配置更高的權重,讓其處理更多的請求,而低配置、高負載的機器,則給其分配較低的權重,降低其系統負載。加權輪詢法可以很好地處理這一問題,并將請求順序按照權重分配到后端。加權輪詢法的代碼實現大致如下:

public class WeightRoundRobin   {       private static Integer pos;       public static String getServer()       {           // 重建一個Map,避免服務器的上下線導致的并發問題           Map<String, Integer> serverMap =                    new HashMap<String, Integer>();           serverMap.putAll(IpMap.serverWeightMap);           // 取得Ip地址List           Set<String> keySet = serverMap.keySet();           Iterator<String> iterator = keySet.iterator();           List<String> serverList = new ArrayList<String>();           while (iterator.hasNext())           {               String server = iterator.next();               int weight = serverMap.get(server);               for (int i = 0; i < weight; i++)                   serverList.add(server);           }           String server = null;           synchronized (pos)           {               if (pos > keySet.size())                   pos = 0;               server = serverList.get(pos);               pos ++;           }           return server;       }   }

與輪詢法類似,只是在獲取服務器地址之前增加了一段權重計算的代碼,根據權重的大小,將地址重復地增加到服務器地址列表中,權重越大,該服務器每輪所獲得的請求數量越多。

 

加權隨機(Weight Random)法

與加權輪詢法類似,加權隨機法也是根據后端服務器不同的配置和負載情況來配置不同的權重。不同的是,它是按照權重來隨機選擇服務器的,而不是順序。加權隨機法的代碼實現如下:

public class WeightRandom   {       public static String getServer()       {           // 重建一個Map,避免服務器的上下線導致的并發問題           Map<String, Integer> serverMap =                    new HashMap<String, Integer>();           serverMap.putAll(IpMap.serverWeightMap);           // 取得Ip地址List           Set<String> keySet = serverMap.keySet();           Iterator<String> iterator = keySet.iterator();           List<String> serverList = new ArrayList<String>();           while (iterator.hasNext())           {               String server = iterator.next();               int weight = serverMap.get(server);               for (int i = 0; i < weight; i++)                   serverList.add(server);           }           java.util.Random random = new java.util.Random();           int randomPos = random.nextInt(serverList.size());           return serverList.get(randomPos);       }   }

這段代碼相當于是隨機法和加權輪詢法的結合,比較好理解,就不解釋了。

 

最小連接數(Least Connections)法

前面幾種方法費盡心思來實現服務消費者請求次數分配的均衡,當然這么做是沒錯的,可以為后端的多臺服務器平均分配工作量,最大程度地提高服務器的利用率,但是實際情況是否真的如此?實際情況中,請求次數的均衡真的能代表負載的均衡嗎?這是一個值得思考的問題。

上面的問題,再換一個角度來說就是:以后端服務器的視角來觀察系統的負載,而非請求發起方來觀察。最小連接數法便屬于此類。

最小連接數算法比較靈活和智能,由于后端服務器的配置不盡相同,對于請求的處理有快有慢,它正是根據后端服務器當前的連接情況,動態地選取其中當前積壓連接數最少的一臺服務器來處理當前請求,盡可能地提高后端服務器的利用效率,將負載合理地分流到每一臺機器。由于最小連接數設計服務器連接數的匯總和感知,設計與實現較為繁瑣,此處就不說它的實現了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本a级片电影一区二区| 国产97人人超碰caoprom| 日韩av手机在线观看| 国产主播欧美精品| 亚洲精品国产精品久久清纯直播| 久久av中文字幕| 日韩高清a**址| 亚洲欧美日韩另类| 国产不卡视频在线| 国产精自产拍久久久久久蜜| 日本电影亚洲天堂| 国产综合福利在线| 亚洲人午夜色婷婷| 国自产精品手机在线观看视频| 日日噜噜噜夜夜爽亚洲精品| 国产精品丝袜久久久久久不卡| 国产免费一区二区三区香蕉精| 久久精品在线播放| 久久中文久久字幕| 欧美亚州一区二区三区| 精品美女久久久久久免费| 日本久久久久久久久久久| 亚洲男人av在线| 92国产精品久久久久首页| 国产成人久久久精品一区| 久久久人成影片一区二区三区观看| 亚洲女人天堂色在线7777| 国产精品91久久久| 国产91在线视频| 欧美性受xxxx白人性爽| 91wwwcom在线观看| 少妇精69xxtheporn| 欧美激情久久久久久| 久久久最新网址| 中文字幕亚洲一区| 欧美亚洲成人网| 中文字幕欧美国内| 欧美巨猛xxxx猛交黑人97人| 亚洲精品999| 亚洲精品456在线播放狼人| 久久精品免费电影| 国产免费成人av| 色综合五月天导航| 亚洲www视频| 欧美丰满老妇厨房牲生活| 国产日韩在线亚洲字幕中文| 亚洲精品久久久久久久久久久久| 欧美激情一区二区三区高清视频| 91超碰caoporn97人人| 亚洲欧美另类人妖| 最新国产精品亚洲| 精品亚洲一区二区三区| 亚洲免费成人av电影| 日韩高清a**址| 成人免费视频在线观看超级碰| 国产欧美精品一区二区三区介绍| 欧美裸体男粗大视频在线观看| 欧美乱妇高清无乱码| 国产精品美女主播在线观看纯欲| 国产精品一区=区| 九九热r在线视频精品| 国产在线视频91| 亚洲色图欧美制服丝袜另类第一页| 中文字幕久久久av一区| 精品少妇v888av| 亚洲欧美日韩在线高清直播| 日韩美女在线观看| 成人网欧美在线视频| 中文字幕成人精品久久不卡| 日韩欧美在线视频观看| 日韩高清电影好看的电视剧电影| 中文字幕亚洲激情| 国产精品青草久久久久福利99| 亚洲精选在线观看| 日韩av在线天堂网| 日韩中文字幕免费| 国产精品18久久久久久麻辣| 久久国产天堂福利天堂| 亚洲第一精品久久忘忧草社区| 黑人精品xxx一区一二区| 欧美性视频在线| 亚洲激情视频在线| 日韩天堂在线视频| 久热爱精品视频线路一| 亚洲国产精品va在线| 国产综合视频在线观看| 久久天天躁日日躁| www国产亚洲精品久久网站| 国产成人一区二区三区| 亚洲美女动态图120秒| 久久久久久久电影一区| 精品亚洲国产成av人片传媒| 一本一本久久a久久精品综合小说| 国产女精品视频网站免费| 精品久久久精品| 色av吧综合网| 亚洲wwwav| 97久久精品人人澡人人爽缅北| 96精品久久久久中文字幕| 日本一区二区三区四区视频| 欧美高清在线播放| 国产精品网站视频| 亚洲美女又黄又爽在线观看| 国产欧美一区二区三区四区| 亚洲国产91精品在线观看| 青青久久aⅴ北条麻妃| 国产一区二区三区毛片| 国产精品久久久久国产a级| 亚洲free性xxxx护士白浆| 久久综合久久美利坚合众国| 国产精品成人观看视频国产奇米| 欧美性一区二区三区| 97在线免费视频| 国产中文字幕日韩| 亚洲欧美一区二区激情| 国产精品一区二区电影| 国产欧美日韩精品丝袜高跟鞋| 成年无码av片在线| 久久久精品久久久| 3344国产精品免费看| 亚洲第一精品久久忘忧草社区| 亚洲第一在线视频| 亚洲在线www| 精品久久中文字幕久久av| 久久香蕉精品香蕉| 成人久久久久久久| 国产亚洲精品久久久久动| 国内精品中文字幕| 欧美日韩国产一区二区| 美女福利精品视频| 国产精品日韩一区| 亚洲a中文字幕| 在线看国产精品| 亚洲电影免费观看高清完整版| 亚洲最新av在线| 黄色一区二区在线| 高清欧美电影在线| 91精品国产色综合久久不卡98口| 在线亚洲国产精品网| 91产国在线观看动作片喷水| 色伦专区97中文字幕| 国产亚洲欧洲黄色| 亚洲精品久久久久久久久久久久| 亚洲最大福利视频网站| 日本欧美一级片| 欧美午夜激情小视频| 久久黄色av网站| 日本在线精品视频| 日韩精品免费在线视频观看| 青青久久av北条麻妃黑人| 欧美成人一二三| 91在线高清免费观看| 亚洲剧情一区二区| 中文字幕日韩欧美精品在线观看| 日韩亚洲精品电影| 亚洲国产精品va在线看黑人动漫| 欧美成人亚洲成人日韩成人| 久久综合免费视频| 亚洲成人激情在线观看| 国产精品第一视频| 在线日韩精品视频| 日韩国产激情在线| 精品国产1区2区| 日韩av毛片网|