成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Nacos之隨機權重負載均衡算法

開發 前端 算法
Nacos在Client選擇節點時提供了一種基于權重的隨機算法,通過源碼分析掌握其實現原理,方便實戰中加以運用。

引言

Nacos在Client選擇節點時提供了一種基于權重的隨機算法,通過源碼分析掌握其實現原理,方便實戰中加以運用。

一、內容提要

下面以圖示的方式貫穿下隨機權重負載均衡算法的流程:

節點列表

假設注冊了5個節點,每個節點的權重如下。

組織遞增數組

目的在于形成weights數組,該數組元素取值[0~1]范圍,元素逐個遞增,計算過程如下圖示。另外注意非健康節點或者權重小于等于0的不會被選擇。

隨機算法

通過生成[0~1]范圍的隨機數,通過二分法查找遞增數組weights[]接近的index,再從注冊節點列表中返回節點。

二、源碼分析

隨機權重負載均衡算法是在NacosNamingService#selectOneHealthyInstance提供,一起走查下。

  1. @Override 
  2. public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe) 
  3.   throws NacosException { 
  4.   return selectOneHealthyInstance(serviceName, groupName, new ArrayList<String>(), subscribe); 
  1. @Override 
  2. public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters, 
  3.                                          boolean subscribe) throws NacosException { 
  4.   String clusterString = StringUtils.join(clusters, ","); 
  5.   // 注解@1 
  6.   if (subscribe) { 
  7.     ServiceInfo serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, clusterString); 
  8.     if (null == serviceInfo) { 
  9.       serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString); 
  10.     } 
  11.     return Balancer.RandomByWeight.selectHost(serviceInfo); 
  12.   } else { 
  13.     // 注解@2 
  14.     ServiceInfo serviceInfo = clientProxy 
  15.       .queryInstancesOfService(serviceName, groupName, clusterString, 0, false); 
  16.     return Balancer.RandomByWeight.selectHost(serviceInfo); 
  17.   } 

注解@1 已訂閱「從緩存獲取注冊節點列表」,默認subscribe為true。

注解@2 從 「從服務器獲取注冊節點列表」

  1. protected static Instance getHostByRandomWeight(List<Instance> hosts) { 
  2.   NAMING_LOGGER.debug("entry randomWithWeight"); 
  3.   if (hosts == null || hosts.size() == 0) { 
  4.     NAMING_LOGGER.debug("hosts == null || hosts.size() == 0"); 
  5.     return null
  6.   } 
  7.   NAMING_LOGGER.debug("new Chooser"); 
  8.   List<Pair<Instance>> hostsWithWeight = new ArrayList<Pair<Instance>>(); 
  9.   for (Instance host : hosts) { 
  10.     if (host.isHealthy()) {  // 注解@3 
  11.       hostsWithWeight.add(new Pair<Instance>(host, host.getWeight())); 
  12.     } 
  13.   } 
  14.   NAMING_LOGGER.debug("for (Host host : hosts)"); 
  15.   Chooser<String, Instance> vipChooser = new Chooser<String, Instance>("www.taobao.com"); 
  16.   // 注解@4 
  17.   vipChooser.refresh(hostsWithWeight); 
  18.   NAMING_LOGGER.debug("vipChooser.refresh"); 
  19.   // 注解@5 
  20.   return vipChooser.randomWithWeight(); 

注解@3 非健康節點不會被選中,組裝Pair的列表,包含健康節點的權重和Host信息

注解@4 刷新需要的數據,具體包括三部分:所有健康節點權重求和、計算每個健康節點權重占比、組織遞增數組。

  1. public void refresh() { 
  2.     Double originWeightSum = (double) 0; 
  3.     // 注解@4.1 
  4.     for (Pair<T> item : itemsWithWeight) { 
  5.  
  6.         double weight = item.weight(); 
  7.         // ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest 
  8.         // weight小于等于 0的將會剔除 
  9.         if (weight <= 0) { 
  10.             continue
  11.         } 
  12.  
  13.         items.add(item.item()); 
  14.  
  15.         // 值如果無窮大 
  16.         if (Double.isInfinite(weight)) { 
  17.             weight = 10000.0D; 
  18.         } 
  19.  
  20.         // 值如果為非數字值 
  21.         if (Double.isNaN(weight)) { 
  22.             weight = 1.0D; 
  23.         } 
  24.  
  25.         // 累加權重總和 
  26.         originWeightSum += weight; 
  27.     } 
  28.  
  29.     // 注解@4.2 
  30.     double[] exactWeights = new double[items.size()]; 
  31.     int index = 0; 
  32.     for (Pair<T> item : itemsWithWeight) { 
  33.         double singleWeight = item.weight(); 
  34.         //ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest 
  35.         if (singleWeight <= 0) { 
  36.             continue
  37.         } 
  38.         // 每個節點權重的占比 
  39.         exactWeights[index++] = singleWeight / originWeightSum; 
  40.     } 
  41.  
  42.     // 注解@4.3 
  43.     weights = new double[items.size()]; 
  44.     double randomRange = 0D; 
  45.     for (int i = 0; i < index; i++) { 
  46.         weights[i] = randomRange + exactWeights[i]; 
  47.         randomRange += exactWeights[i]; 
  48.     } 
  49.    
  50.     double doublePrecisionDelta = 0.0001; 
  51.  
  52.     if (index == 0 || (Math.abs(weights[index - 1] - 1) < doublePrecisionDelta)) { 
  53.         return
  54.     } 
  55.     throw new IllegalStateException( 
  56.             "Cumulative Weight caculate wrong , the sum of probabilities does not equals 1."); 

注解@4.1 所有健康節點權重求和originWeightSum

注解@4.2 計算每個健康節點權重占比exactWeights數組

注解@4.3 組織遞增數組weights,每個元素值為數組前面元素之和

以一個例子來表示這個過程,假設有5個節點:

  1. 1.2.3.4 100 
  2. 1.2.3.5 100 
  3. 1.2.3.6 100 
  4. 1.2.3.7 80 
  5. 1.2.3.8 60 

步驟一 計算節點權重求和

  • originWeightSum = 100 + 100 + 100 + 80 + 60 = 440

步驟二 計算每個節點權重占比

  • exactWeights[0] = 0.2272
  • exactWeights[1] = 0.2272
  • exactWeights[2] = 0.2272
  • exactWeights[3] = 0.1818
  • exactWeights[4] = 0.1363

步驟三 組織遞增數組weights

  • weights[0] = 0.2272
  • weights[1] = 0.4544
  • weights[2] = 0.6816
  • weights[3] = 0.8634
  • weights[4] = 1

注解@5 隨機選取一個,邏輯如下:

  1. public T randomWithWeight() { 
  2.     Ref<T> ref = this.ref; 
  3.     // 注解@5.1 
  4.     double random = ThreadLocalRandom.current().nextDouble(0, 1); 
  5.     // 注解@5.2 
  6.     int index = Arrays.binarySearch(ref.weights, random); 
  7.     // 注解@5.3 
  8.     if (index < 0) { 
  9.         index = -index - 1; 
  10.     } else { 
  11.         // 注解@5.4 
  12.         return ref.items.get(index); 
  13.     } 
  14.  
  15.     // 返回選中的元素 
  16.     if (index >= 0 && index < ref.weights.length) { 
  17.         if (random < ref.weights[index]) { 
  18.             return ref.items.get(index); 
  19.         } 
  20.     } 
  21.  
  22.     /* This should never happen, but it ensures we will return a correct 
  23.      * object in case there is some floating point inequality problem 
  24.      * wrt the cumulative probabilities. */ 
  25.     return ref.items.get(ref.items.size() - 1); 

注解@5.1 產生0到1區間的隨機數

注解@5.2 二分法查找數組中接近的值

注解@5.3 沒有命中返回插入數組理想索引值

注解@5.4 命中直接返回選中節點

小結: 一種基于權重的隨機算法的實現過程,扒開看也不復雜。

本文轉載自微信公眾號「瓜農老梁」,可以通過以下二維碼關注。轉載本文請聯系瓜農老梁公眾號。

 

責任編輯:武曉燕 來源: 瓜農老梁
相關推薦

2021-08-23 06:59:22

Nacos負載均衡客戶端

2010-05-04 16:10:51

負載均衡算法

2019-07-12 09:14:07

分布式系統負載均衡

2019-03-18 10:44:41

負載均衡DNSUDP

2018-11-07 10:12:37

2018-04-10 10:49:17

負載均衡算法服務器

2010-04-27 13:12:04

負載均衡算法

2024-12-20 12:12:19

Redis負載均衡節點

2023-10-31 16:38:02

注冊中心負載均衡器

2019-09-27 08:18:13

負載均衡核心Key

2010-05-10 14:20:24

負載均衡技術

2010-04-26 14:44:36

負載均衡設備

2021-01-26 05:35:24

負載均衡系統設計

2021-04-22 07:47:46

Linux進程管理

2010-04-28 12:24:42

網站負載均衡

2010-04-26 17:07:59

網絡負載均衡

2017-07-03 08:08:25

負載均衡分類

2019-12-27 09:29:46

負載均衡算法哈希算法

2023-11-28 15:32:30

負載均衡算法

2010-04-26 14:52:37

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 少妇性l交大片免费一 | 亚洲综合在线播放 | 国产精品一区二区电影 | 久久久久综合 | 成人网在线看 | 日本天天操 | 欧美一级毛片在线播放 | 欧产日产国产精品99 | 国产精品免费一区二区三区四区 | 欧美成人免费 | 成人免费一区二区三区牛牛 | 伊人网国产 | 久操国产 | 久久久久亚洲精品中文字幕 | 欧美在线一区二区视频 | 91视频网 | 国产视频久久久 | 日韩欧美国产精品 | 国产精品视频久久久 | 久久99精品久久久久久 | 国产综合av | 亚洲成人精品视频 | 久久久久久综合 | 久久久久久久久久久高潮一区二区 | 日韩在线观看 | 国产精品久久久久久网站 | 神马福利 | 国产人成在线观看 | 国产小视频精品 | 精品视频在线观看 | www.久久.com| 中文字幕日韩欧美一区二区三区 | 欧美日韩一区二区三区视频 | 久久久久久久一区 | aaa大片免费观看 | 色综合天天天天做夜夜夜夜做 | 国产午夜精品一区二区三区嫩草 | 成人婷婷 | 一区二区视频在线观看 | 亚洲综合伊人 | 91.com在线观看 |