欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解SpringCloud的負(fù)載均衡

 更新時(shí)間:2021年03月11日 09:08:52   作者:拾萬(wàn)個(gè)為什么  
這篇文章主要介紹了SpringCloud的負(fù)載均衡的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用SpringCloud,感興趣的朋友可以了解下

一.什么是負(fù)載均衡

  負(fù)載均衡(Load-balance LB),指的是將用戶的請(qǐng)求平攤分配到各個(gè)服務(wù)器上,從而達(dá)到系統(tǒng)的高可用。常見的負(fù)載均衡軟件有Nginx、lvs等。

二.負(fù)載均衡的簡(jiǎn)單分類

  1)集中式LB:集中式負(fù)載均衡指的是,在服務(wù)消費(fèi)者(client)和服務(wù)提供者(provider)之間提供負(fù)載均衡設(shè)施,通過(guò)該設(shè)施把消費(fèi)者(client)的請(qǐng)求通過(guò)某種策略轉(zhuǎn)發(fā)給服務(wù)提供者(provider),常見的集中式負(fù)載均衡是Nginx;

  2)進(jìn)程式LB:將負(fù)載均衡的邏輯集成到消費(fèi)者(client)身上,即消費(fèi)者從服務(wù)注冊(cè)中心獲取服務(wù)列表,獲知有哪些地址可用,再?gòu)倪@些地址里選出合適的服務(wù)器,springCloud的Ribbon就是一個(gè)進(jìn)程式的負(fù)載均衡工具。

三.為什么需要做負(fù)載均衡

  1) 不做負(fù)載均衡,可能導(dǎo)致某臺(tái)機(jī)子負(fù)荷太重而掛掉;

  2)導(dǎo)致資源浪費(fèi),比如某些機(jī)子收到太多的請(qǐng)求,肯定會(huì)導(dǎo)致某些機(jī)子收到很少請(qǐng)求甚至收不到請(qǐng)求,這樣會(huì)浪費(fèi)系統(tǒng)資源。 

四.springCloud如何開啟負(fù)載均衡

  1)在消費(fèi)者子工程的pom.xml文件的加入相關(guān)依賴(https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon/1.4.7.RELEASE);

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-ribbon</artifactId>
 <version>1.4.7.RELEASE</version>
</dependency>

   消費(fèi)者需要獲取服務(wù)注冊(cè)中心的注冊(cè)列表信息,把Eureka的依賴包也放進(jìn)pom.xml

 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka-server</artifactId>
   <version>1.4.7.RELEASE</version>
 </dependency>

  2)在application.yml里配置服務(wù)注冊(cè)中心的信息

  在該消費(fèi)者(client)的application.yml里配置Eureka的信息

#配置Eureka
eureka:
 client:
 #是否注冊(cè)自己到服務(wù)注冊(cè)中心,消費(fèi)者不用提供服務(wù)
 register-with-eureka: false
 service-url:
  #訪問(wèn)的url
  defaultZone: http://localhost:8002/eureka/

  3)在消費(fèi)者啟動(dòng)類上面加上注解@EnableEurekaClient

@EnableEurekaClient

  4)在配置文件的Bean上加上

 @Bean
 @LoadBalanced
 public RestTemplate getRestTemplate(){
  return new RestTemplate();
 }

五.IRule

 什么是IRule

  IRule接口代表負(fù)載均衡的策略,它的不同的實(shí)現(xiàn)類代表不同的策略,它的四種實(shí)現(xiàn)類和它的關(guān)系如下()

說(shuō)明一下(idea找Irule的方法:ctrl+n   填入IRule進(jìn)行查找)

1.RandomRule:表示隨機(jī)策略,它將從服務(wù)清單中隨機(jī)選擇一個(gè)服務(wù);

public class RandomRule extends AbstractLoadBalancerRule {
 public RandomRule() {
 }

 @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
 //傳入一個(gè)負(fù)載均衡器
 public Server choose(ILoadBalancer lb, Object key) {
  if (lb == null) {
   return null;
  } else {
   Server server = null;
   while(server == null) {
    if (Thread.interrupted()) {
     return null;
    }
    //通過(guò)負(fù)載均衡器獲取對(duì)應(yīng)的服務(wù)列表
    List<Server> upList = lb.getReachableServers();
    //通過(guò)負(fù)載均衡器獲取全部服務(wù)列表
    List<Server> allList = lb.getAllServers();
    int serverCount = allList.size();
    if (serverCount == 0) {
     return null;
    }
    //獲取一個(gè)隨機(jī)數(shù)
    int index = this.chooseRandomInt(serverCount);
    //通過(guò)這個(gè)隨機(jī)數(shù)從列表里獲取服務(wù)
    server = (Server)upList.get(index);
    if (server == null) {
     //當(dāng)前線程轉(zhuǎn)為就緒狀態(tài),讓出cpu
     Thread.yield();
    } else {
     if (server.isAlive()) {
      return server;
     }

     server = null;
     Thread.yield();
    }
   }

   return server;
  }
 }

  小結(jié):通過(guò)獲取到的所有服務(wù)的數(shù)量,以這個(gè)數(shù)量為標(biāo)準(zhǔn)獲取一個(gè)(0,服務(wù)數(shù)量)的數(shù)作為獲取服務(wù)實(shí)例的下標(biāo),從而獲取到服務(wù)實(shí)例

2.ClientConfigEnabledRoundRobinRule:ClientConfigEnabledRoundRobinRule并沒有實(shí)現(xiàn)什么特殊的處理邏輯,但是他的子類可以實(shí)現(xiàn)一些高級(jí)策略, 當(dāng)一些本身的策略無(wú)法實(shí)現(xiàn)某些需求的時(shí)候,它也可以做為父類幫助實(shí)現(xiàn)某些策略,一般情況下我們都不會(huì)使用它;

public class ClientConfigEnabledRoundRobinRule extends AbstractLoadBalancerRule {
 //使用“4”中的RoundRobinRule策略
 RoundRobinRule roundRobinRule = new RoundRobinRule();

 public ClientConfigEnabledRoundRobinRule() {
 }

 public void initWithNiwsConfig(IClientConfig clientConfig) {
  this.roundRobinRule = new RoundRobinRule();
 }

 public void setLoadBalancer(ILoadBalancer lb) {
  super.setLoadBalancer(lb);
  this.roundRobinRule.setLoadBalancer(lb);
 }

 public Server choose(Object key) {
  if (this.roundRobinRule != null) {
   return this.roundRobinRule.choose(key);
  } else {
   throw new IllegalArgumentException("This class has not been initialized with the RoundRobinRule class");
  }
 }
}

  小結(jié):用來(lái)作為父類,子類通過(guò)實(shí)現(xiàn)它來(lái)實(shí)現(xiàn)一些高級(jí)負(fù)載均衡策略

1)ClientConfigEnabledRoundRobinRule的子類BestAvailableRule:從該策略的名字就可以知道,bestAvailable的意思是最好獲取的,該策略的作用是獲取到最空閑的服務(wù)實(shí)例;

public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule {
 //注入負(fù)載均衡器,它可以選擇服務(wù)實(shí)例
 private LoadBalancerStats loadBalancerStats;

 public BestAvailableRule() {
 }

 public Server choose(Object key) {
  //假如負(fù)載均衡器實(shí)例為空,采用它父類的負(fù)載均衡機(jī)制,也就是輪詢機(jī)制,因?yàn)樗母割惒捎玫木褪禽喸儥C(jī)制
  if (this.loadBalancerStats == null) {
   return super.choose(key);
  } else {
   //獲取所有服務(wù)實(shí)例并放入列表里
   List<Server> serverList = this.getLoadBalancer().getAllServers();
   //并發(fā)量
   int minimalConcurrentConnections = 2147483647;
   long currentTime = System.currentTimeMillis();
   Server chosen = null;
   Iterator var7 = serverList.iterator();
   //遍歷服務(wù)列表
   while(var7.hasNext()) {
    Server server = (Server)var7.next();
    ServerStats serverStats = this.loadBalancerStats.getSingleServerStat(server);
    //淘汰掉已經(jīng)負(fù)載的服務(wù)實(shí)例
    if (!serverStats.isCircuitBreakerTripped(currentTime)) {
     //獲得當(dāng)前服務(wù)的請(qǐng)求量(并發(fā)量)
     int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
     //找出并發(fā)了最小的服務(wù)
     if (concurrentConnections < minimalConcurrentConnections) {
      minimalConcurrentConnections = concurrentConnections;
      chosen = server;
     }
    }
   }

   if (chosen == null) {
    return super.choose(key);
   } else {
    return chosen;
   }
  }
 }

 public void setLoadBalancer(ILoadBalancer lb) {
  super.setLoadBalancer(lb);
  if (lb instanceof AbstractLoadBalancer) {
   this.loadBalancerStats = ((AbstractLoadBalancer)lb).getLoadBalancerStats();
  }

 }
}

   小結(jié):ClientConfigEnabledRoundRobinRule子類之一,獲取到并發(fā)了最少的服務(wù)

2)ClientConfigEnabledRoundRobinRule的另一個(gè)子類是PredicateBasedRule:通過(guò)源碼可以看出它是一個(gè)抽象類,它的抽象方法getPredicate()返回一個(gè)AbstractServerPredicate的實(shí)例,然后它的choose方法調(diào)用AbstractServerPredicate類的chooseRoundRobinAfterFiltering方法獲取具體的Server實(shí)例并返回

public abstract class PredicateBasedRule extends ClientConfigEnabledRoundRobinRule {
 public PredicateBasedRule() {
 }
 //獲取AbstractServerPredicate對(duì)象
 public abstract AbstractServerPredicate getPredicate();

 public Server choose(Object key) {
  //獲取當(dāng)前策略的負(fù)載均衡器
  ILoadBalancer lb = this.getLoadBalancer();
  //通過(guò)AbstractServerPredicate的子類過(guò)濾掉一部分實(shí)例(它實(shí)現(xiàn)了Predicate)
  //以輪詢的方式從過(guò)濾后的服務(wù)里選擇一個(gè)服務(wù)
  Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
  return server.isPresent() ? (Server)server.get() : null;
 }
}

  再看看它的chooseRoundRobinAfterFiltering()方法是如何實(shí)現(xiàn)的

public Optional<Server> chooseRoundRobinAfterFiltering(List<Server> servers, Object loadBalancerKey) {
  List<Server> eligible = this.getEligibleServers(servers, loadBalancerKey);
  return eligible.size() == 0 ? Optional.absent() : Optional.of(eligible.get(this.incrementAndGetModulo(eligible.size())));
 }

  是這樣的,先通過(guò)this.getEligibleServers(servers, loadBalancerKey)方法獲取一部分實(shí)例,然后判斷這部分實(shí)例是否為空,如果不為空則調(diào)用eligible.get(this.incrementAndGetModulo(eligible.size())方法從這部分實(shí)例里獲取一個(gè)服務(wù),點(diǎn)進(jìn)this.getEligibleServers看

public List<Server> getEligibleServers(List<Server> servers, Object loadBalancerKey) {
  if (loadBalancerKey == null) {
   return ImmutableList.copyOf(Iterables.filter(servers, this.getServerOnlyPredicate()));
  } else {
   List<Server> results = Lists.newArrayList();
   Iterator var4 = servers.iterator();

   while(var4.hasNext()) {
    Server server = (Server)var4.next();
    //條件滿足
    if (this.apply(new PredicateKey(loadBalancerKey, server))) {
     //添加到集合里
     results.add(server);
    }
   }

   return results;
  }
 }

  getEligibleServers方法是根據(jù)this.apply(new PredicateKey(loadBalancerKey, server))進(jìn)行過(guò)濾的,如果滿足,就添加到返回的集合中。符合什么條件才可以進(jìn)行過(guò)濾呢?可以發(fā)現(xiàn),apply是用this調(diào)用的,this指的是AbstractServerPredicate(它的類對(duì)象),但是,該類是個(gè)抽象類,該實(shí)例是不存在的,需要子類去實(shí)現(xiàn),它的子類在這里暫時(shí)不是看了,以后有空再深入學(xué)習(xí)下,它的子類如下,實(shí)現(xiàn)哪個(gè)子類,就用什么 方式過(guò)濾。

   再回到chooseRoundRobinAfterFiltering()方法,剛剛說(shuō)完它通過(guò) getEligibleServers方法過(guò)濾并獲取到一部分實(shí)例,然后再通過(guò)this.incrementAndGetModulo(eligible.size())方法從這部分實(shí)例里選擇一個(gè)實(shí)例返回,該方法的意思是直接返回下一個(gè)整數(shù)(索引值),通過(guò)該索引值從返回的實(shí)例列表中取得Server實(shí)例。

private int incrementAndGetModulo(int modulo) {
  //當(dāng)前下標(biāo)
  int current;
  //下一個(gè)下標(biāo)
  int next;
  do {
   //獲得當(dāng)前下標(biāo)值
   current = this.nextIndex.get();
   next = (current + 1) % modulo;
  } while(!this.nextIndex.compareAndSet(current, next) || current >= modulo);

  return current;
 }

  源碼擼明白了,再來(lái)理一下chooseRoundRobinAfterFiltering()的思路:先通過(guò)getEligibleServers()方法獲得一部分服務(wù)實(shí)例,再?gòu)倪@部分服務(wù)實(shí)例里拿到當(dāng)前服務(wù)實(shí)例的下一個(gè)服務(wù)對(duì)象使用。

  小結(jié):通過(guò)AbstractServerPredicate的chooseRoundRobinAfterFiltering方法進(jìn)行過(guò)濾,獲取備選的服務(wù)實(shí)例清單,然后用線性輪詢選擇一個(gè)實(shí)例,是一個(gè)抽象類,過(guò)濾策略在AbstractServerPredicate的子類中具體實(shí)現(xiàn)

3.RetryRule:是對(duì)選定的負(fù)載均衡策略加上重試機(jī)制,即在一個(gè)配置好的時(shí)間段內(nèi)(默認(rèn)500ms),當(dāng)選擇實(shí)例不成功,則一直嘗試使用subRule的方式選擇一個(gè)可用的實(shí)例,在調(diào)用時(shí)間到達(dá)閥值的時(shí)候還沒找到可用服務(wù),則返回空,如果沒有配置負(fù)載策略,默認(rèn)輪詢(即“4”中的輪詢);

  先貼上它的源碼

public class RetryRule extends AbstractLoadBalancerRule {
 //從這可以看出,默認(rèn)使用輪詢機(jī)制
 IRule subRule = new RoundRobinRule();
 //500秒的閥值
 long maxRetryMillis = 500L;
 //無(wú)參構(gòu)造函數(shù)
 public RetryRule() {
 }
 //使用輪詢機(jī)制
 public RetryRule(IRule subRule) {
  this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
 }

 public RetryRule(IRule subRule, long maxRetryMillis) {
  this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
  this.maxRetryMillis = maxRetryMillis > 0L ? maxRetryMillis : 500L;
 }
 
 public void setRule(IRule subRule) {
  this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
 }

 public IRule getRule() {
  return this.subRule;
 }
 //設(shè)置最大耗時(shí)時(shí)間(閥值),最多重試多久
 public void setMaxRetryMillis(long maxRetryMillis) {
  if (maxRetryMillis > 0L) {
   this.maxRetryMillis = maxRetryMillis;
  } else {
   this.maxRetryMillis = 500L;
  }

 }
 //獲取重試的時(shí)間
 public long getMaxRetryMillis() {
  return this.maxRetryMillis;
 }
 //設(shè)置負(fù)載均衡器,用以獲取服務(wù)
 public void setLoadBalancer(ILoadBalancer lb) {
  super.setLoadBalancer(lb);
  this.subRule.setLoadBalancer(lb);
 }
 //通過(guò)負(fù)載均衡器選擇服務(wù)
 public Server choose(ILoadBalancer lb, Object key) {
  long requestTime = System.currentTimeMillis();
  //當(dāng)前時(shí)間+閥值 = 截止時(shí)間
  long deadline = requestTime + this.maxRetryMillis;
  Server answer = null;
  answer = this.subRule.choose(key);
  //獲取到服務(wù)直接返回
  if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline) {
   InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());
   //獲取不到服務(wù)的情況下反復(fù)獲取
   while(!Thread.interrupted()) {
    answer = this.subRule.choose(key);
    if (answer != null && answer.isAlive() || System.currentTimeMillis() >= deadline) {
     break;
    }

    Thread.yield();
   }

   task.cancel();
  }

  return answer != null && answer.isAlive() ? answer : null;
 }

 public Server choose(Object key) {
  return this.choose(this.getLoadBalancer(), key);
 }

 public void initWithNiwsConfig(IClientConfig clientConfig) {
 }
}

  小結(jié):采用RoundRobinRule的選擇機(jī)制,進(jìn)行反復(fù)嘗試,當(dāng)花費(fèi)時(shí)間超過(guò)設(shè)置的閾值maxRetryMills時(shí),就返回null

4.RoundRobinRule:輪詢策略,它會(huì)從服務(wù)清單中按照輪詢的方式依次選擇每個(gè)服務(wù)實(shí)例,它的工作原理是:直接獲取下一個(gè)可用實(shí)例,如果超過(guò)十次沒有獲取到可用的服務(wù)實(shí)例,則返回空且報(bào)出異常信息;

public class RoundRobinRule extends AbstractLoadBalancerRule {
 private AtomicInteger nextServerCyclicCounter;
 private static final boolean AVAILABLE_ONLY_SERVERS = true;
 private static final boolean ALL_SERVERS = false;
 private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);

 public RoundRobinRule() {
  this.nextServerCyclicCounter = new AtomicInteger(0);
 }

 public RoundRobinRule(ILoadBalancer lb) {
  this();
  this.setLoadBalancer(lb);
 }

 public Server choose(ILoadBalancer lb, Object key) {
  if (lb == null) {
   log.warn("no load balancer");
   return null;
  } else {
   Server server = null;
   int count = 0;

   while(true) {
    //選擇十次,十次都沒選到可用服務(wù)就返回空
    if (server == null && count++ < 10) {
     List<Server> reachableServers = lb.getReachableServers();
     List<Server> allServers = lb.getAllServers();
     int upCount = reachableServers.size();
     int serverCount = allServers.size();
     if (upCount != 0 && serverCount != 0) {
      int nextServerIndex = this.incrementAndGetModulo(serverCount);
      server = (Server)allServers.get(nextServerIndex);
      if (server == null) {
       Thread.yield();
      } else {
       if (server.isAlive() && server.isReadyToServe()) {
        return server;
       }

       server = null;
      }
      continue;
     }

     log.warn("No up servers available from load balancer: " + lb);
     return null;
    }

    if (count >= 10) {
     
     log.warn("No available alive servers after 10 tries from load balancer: " + lb);
    }

    return server;
   }
  }
 }
 
 //遞增的形式實(shí)現(xiàn)輪詢
 private int incrementAndGetModulo(int modulo) {
  int current;
  int next;
  do {
   current = this.nextServerCyclicCounter.get();
   next = (current + 1) % modulo;
  } while(!this.nextServerCyclicCounter.compareAndSet(current, next));

  return next;
 }

 public Server choose(Object key) {
  return this.choose(this.getLoadBalancer(), key);
 }

 public void initWithNiwsConfig(IClientConfig clientConfig) {
 }
}

  小結(jié):采用線性輪詢機(jī)制循環(huán)依次選擇每個(gè)服務(wù)實(shí)例,直到選擇到一個(gè)不為空的服務(wù)實(shí)例或循環(huán)次數(shù)達(dá)到10次   

它有個(gè)子類WeightedResponseTimeRule,WeightedResponseTimeRule是對(duì)RoundRobinRule的優(yōu)化。WeightedResponseTimeRule在其父類的基礎(chǔ)上,增加了定時(shí)任務(wù)這個(gè)功能,通過(guò)啟動(dòng)一個(gè)定時(shí)任務(wù)來(lái)計(jì)算每個(gè)服務(wù)的權(quán)重,然后遍歷服務(wù)列表選擇服務(wù)實(shí)例,從而達(dá)到更加優(yōu)秀的分配效果。我們這里把這個(gè)類分為三部分:定時(shí)任務(wù),計(jì)算權(quán)值,選擇服務(wù)

1)定時(shí)任務(wù)

//定時(shí)任務(wù)
void initialize(ILoadBalancer lb) {
  if (this.serverWeightTimer != null) {
   this.serverWeightTimer.cancel();
  }

  this.serverWeightTimer = new Timer("NFLoadBalancer-serverWeightTimer-" + this.name, true);
  //開啟一個(gè)任務(wù),每30秒執(zhí)行一次
  this.serverWeightTimer.schedule(new WeightedResponseTimeRule.DynamicServerWeightTask(), 0L, (long)this.serverWeightTaskTimerInterval);
  WeightedResponseTimeRule.ServerWeight sw = new WeightedResponseTimeRule.ServerWeight();
  sw.maintainWeights();
  Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
   public void run() {
    WeightedResponseTimeRule.logger.info("Stopping NFLoadBalancer-serverWeightTimer-" + WeightedResponseTimeRule.this.name);
    WeightedResponseTimeRule.this.serverWeightTimer.cancel();
   }
  }));
 }

DynamicServerWeightTask()任務(wù)如下:

class DynamicServerWeightTask extends TimerTask {
  DynamicServerWeightTask() {
  }

  public void run() {
   WeightedResponseTimeRule.ServerWeight serverWeight = WeightedResponseTimeRule.this.new ServerWeight();

   try {
    //計(jì)算權(quán)重
    serverWeight.maintainWeights();
   } catch (Exception var3) {
    WeightedResponseTimeRule.logger.error("Error running DynamicServerWeightTask for {}", WeightedResponseTimeRule.this.name, var3);
   }

  }
 }

   小結(jié):調(diào)用initialize方法開啟定時(shí)任務(wù),再在任務(wù)里計(jì)算服務(wù)的權(quán)重

2)計(jì)算權(quán)重:第一步,先算出所有實(shí)例的響應(yīng)時(shí)間;第二步,再根據(jù)所有實(shí)例響應(yīng)時(shí)間,算出每個(gè)實(shí)例的權(quán)重

//用來(lái)存儲(chǔ)權(quán)重
private volatile List<Double> accumulatedWeights = new ArrayList();

//內(nèi)部類
class ServerWeight {
  ServerWeight() {
  }
  //該方法用于計(jì)算權(quán)重
  public void maintainWeights() {
   //獲取負(fù)載均衡器
   ILoadBalancer lb = WeightedResponseTimeRule.this.getLoadBalancer();
   if (lb != null) {
    if (WeightedResponseTimeRule.this.serverWeightAssignmentInProgress.compareAndSet(false, true)) {
     try {
      WeightedResponseTimeRule.logger.info("Weight adjusting job started");
      AbstractLoadBalancer nlb = (AbstractLoadBalancer)lb;
      //獲得每個(gè)服務(wù)實(shí)例的信息
      LoadBalancerStats stats = nlb.getLoadBalancerStats();
      if (stats != null) {
       //實(shí)例的響應(yīng)時(shí)間
       double totalResponseTime = 0.0D;

       ServerStats ss;
       //累加所有實(shí)例的響應(yīng)時(shí)間
       for(Iterator var6 = nlb.getAllServers().iterator(); var6.hasNext(); totalResponseTime += ss.getResponseTimeAvg()) {
        Server server = (Server)var6.next();
        ss = stats.getSingleServerStat(server);
       }

       Double weightSoFar = 0.0D;
       List<Double> finalWeights = new ArrayList();
       Iterator var20 = nlb.getAllServers().iterator();
       //計(jì)算負(fù)載均衡器所有服務(wù)的權(quán)重,公式是weightSoFar = weightSoFar + weight-實(shí)例平均響應(yīng)時(shí)間
       while(var20.hasNext()) {
        Server serverx = (Server)var20.next();
        ServerStats ssx = stats.getSingleServerStat(serverx);
        double weight = totalResponseTime - ssx.getResponseTimeAvg();
        weightSoFar = weightSoFar + weight;
        finalWeights.add(weightSoFar);
       }

       WeightedResponseTimeRule.this.setWeights(finalWeights);
       return;
      }
     } catch (Exception var16) {
      WeightedResponseTimeRule.logger.error("Error calculating server weights", var16);
      return;
     } finally {
      WeightedResponseTimeRule.this.serverWeightAssignmentInProgress.set(false);
     }

    }
   }
  }
 }

3)選擇服務(wù)

@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
 public Server choose(ILoadBalancer lb, Object key) {
  if (lb == null) {
   return null;
  } else {
   Server server = null;

   while(server == null) {
    List<Double> currentWeights = this.accumulatedWeights;
    if (Thread.interrupted()) {
     return null;
    }

    List<Server> allList = lb.getAllServers();
    int serverCount = allList.size();
    if (serverCount == 0) {
     return null;
    }

    int serverIndex = 0;
    
    double maxTotalWeight = currentWeights.size() == 0 ? 0.0D : (Double)currentWeights.get(currentWeights.size() - 1);
    if (maxTotalWeight >= 0.001D && serverCount == currentWeights.size()) {
     //生產(chǎn)0到最大權(quán)重值的隨機(jī)數(shù)
     double randomWeight = this.random.nextDouble() * maxTotalWeight;
     int n = 0;
     //循環(huán)權(quán)重區(qū)間
     for(Iterator var13 = currentWeights.iterator(); var13.hasNext(); ++n) {
      //獲取到循環(huán)的數(shù)
      Double d = (Double)var13.next();
      //假如隨機(jī)數(shù)在這個(gè)區(qū)間內(nèi),就拿該索引d服務(wù)列表獲取對(duì)應(yīng)的實(shí)例
      if (d >= randomWeight) {
       serverIndex = n;
       break;
      }
     }

     server = (Server)allList.get(serverIndex);
    } else {
     server = super.choose(this.getLoadBalancer(), key);
     if (server == null) {
      return server;
     }
    }

    if (server == null) {
     Thread.yield();
    } else {
     if (server.isAlive()) {
      return server;
     }

     server = null;
    }
   }

   return server;
  }
 }

  小結(jié):首先生成了一個(gè)[0,最大權(quán)重值) 區(qū)間內(nèi)的隨機(jī)數(shù),然后遍歷權(quán)重列表,假如當(dāng)前隨機(jī)數(shù)在這個(gè)區(qū)間內(nèi),就通過(guò)該下標(biāo)獲得對(duì)應(yīng)的服務(wù)。

以上就是詳解SpringCloud的負(fù)載均衡的詳細(xì)內(nèi)容,更多關(guān)于SpringCloud 負(fù)載均衡的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    JavaCV實(shí)現(xiàn)讀取視頻信息及自動(dòng)截取封面圖詳解

    javacv可以幫助我們?cè)趈ava中很方便的使用OpenCV以及FFmpeg相關(guān)的功能接口。本文將利用Javacv實(shí)現(xiàn)在視頻網(wǎng)站中常見的讀取視頻信息和自動(dòng)獲取封面圖的功能,感興趣的可以了解一下
    2022-06-06
  • Mybatis分頁(yè)插件PageHelper的配置和簡(jiǎn)單使用方法(推薦)

    Mybatis分頁(yè)插件PageHelper的配置和簡(jiǎn)單使用方法(推薦)

    在使用Java Spring開發(fā)的時(shí)候,Mybatis算是對(duì)數(shù)據(jù)庫(kù)操作的利器了。這篇文章主要介紹了Mybatis分頁(yè)插件PageHelper的配置和使用方法,需要的朋友可以參考下
    2017-12-12
  • dubbo新手學(xué)習(xí)之事件通知實(shí)踐教程

    dubbo新手學(xué)習(xí)之事件通知實(shí)踐教程

    這篇文章主要給大家介紹了關(guān)于dubbo新手學(xué)習(xí)之事件通知實(shí)踐的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring Cache原理解析

    Spring Cache原理解析

    Spring Cache是一個(gè)框架,它提供了基于注解的緩存功能,使得開發(fā)者可以很方便地將緩存集成到他們的應(yīng)用程序中,這篇文章主要介紹了Spring Cache原理解析,需要的朋友可以參考下
    2024-05-05
  • Spring?Bean的8種加載方式總結(jié)

    Spring?Bean的8種加載方式總結(jié)

    以前學(xué)習(xí)Spring框架的時(shí)候,總結(jié)了幾種Bean的加載方式,不過(guò)老師說(shuō)還有其它的加載方式,以下八種并不是全部,但也足以用來(lái)做很多事情了,希望對(duì)大家有所幫助
    2022-10-10
  • Java RandomAccessFile 指定位置實(shí)現(xiàn)文件讀取與寫入

    Java RandomAccessFile 指定位置實(shí)現(xiàn)文件讀取與寫入

    這篇文章主要介紹了Java RandomAccessFile 指定位置實(shí)現(xiàn)文件讀取與寫入的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • SpringBoot與velocity的結(jié)合的示例代碼

    SpringBoot與velocity的結(jié)合的示例代碼

    本篇文章主要介紹了SpringBoot與velocity的結(jié)合的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Java+Selenium調(diào)用JavaScript的方法詳解

    Java+Selenium調(diào)用JavaScript的方法詳解

    這篇文章主要為大家講解了java在利用Selenium操作瀏覽器網(wǎng)站時(shí)候,有時(shí)會(huì)需要用的JavaScript的地方,代碼該如何實(shí)現(xiàn)呢?快跟隨小編一起學(xué)習(xí)一下吧
    2023-01-01
  • Spring AOP的五種通知方式代碼實(shí)例

    Spring AOP的五種通知方式代碼實(shí)例

    這篇文章主要介紹了Spring AOP的五種通知方式代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • SpringBoot?MP簡(jiǎn)單的分頁(yè)查詢測(cè)試實(shí)現(xiàn)步驟分解

    SpringBoot?MP簡(jiǎn)單的分頁(yè)查詢測(cè)試實(shí)現(xiàn)步驟分解

    好久沒水后端的東西了,最近在做vue項(xiàng)目寫前端的代碼,所以cloud也停進(jìn)度了,吃完飯突然記得我沒有在博客里寫分頁(yè)的東西,雖然項(xiàng)目中用到了,但是沒有拎出來(lái),這里就拎出來(lái)看看
    2023-04-04

最新評(píng)論