一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解SpringCloud的負載均衡

詳解SpringCloud的負載均衡

2021-08-23 11:59拾萬個為什么 Java教程

這篇文章主要介紹了SpringCloud的負載均衡的相關資料,幫助大家更好的理解和學習使用SpringCloud,感興趣的朋友可以了解下

一.什么是負載均衡

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

二.負載均衡的簡單分類

1)集中式LB:集中式負載均衡指的是,在服務消費者(client)和服務提供者(provider)之間提供負載均衡設施,通過該設施把消費者(client)的請求通過某種策略轉發(fā)給服務提供者(provider),常見的集中式負載均衡是Nginx;

2)進程式LB:將負載均衡的邏輯集成到消費者(client)身上,即消費者從服務注冊中心獲取服務列表,獲知有哪些地址可用,再從這些地址里選出合適的服務器,springCloud的Ribbon就是一個進程式的負載均衡工具。

三.為什么需要做負載均衡

1) 不做負載均衡,可能導致某臺機子負荷太重而掛掉;

2)導致資源浪費,比如某些機子收到太多的請求,肯定會導致某些機子收到很少請求甚至收不到請求,這樣會浪費系統(tǒng)資源。

四.springCloud如何開啟負載均衡

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

  1. <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-ribbon</artifactId>
  5. <version>1.4.7.RELEASE</version>
  6. </dependency>

消費者需要獲取服務注冊中心的注冊列表信息,把Eureka的依賴包也放進pom.xml

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka-server</artifactId>
  4. <version>1.4.7.RELEASE</version>
  5. </dependency>

2)在application.yml里配置服務注冊中心的信息

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

  1. #配置Eureka
  2. eureka:
  3. client:
  4. #是否注冊自己到服務注冊中心,消費者不用提供服務
  5. register-with-eureka: false
  6. service-url:
  7. #訪問的url
  8. defaultZone: http://localhost:8002/eureka/

3)在消費者啟動類上面加上注解@EnableEurekaClient

  1. @EnableEurekaClient

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

  1. @Bean
  2. @LoadBalanced
  3. public RestTemplate getRestTemplate(){
  4. return new RestTemplate();
  5. }

五.IRule

什么是IRule

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

詳解SpringCloud的負載均衡

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

1.RandomRule:表示隨機策略,它將從服務清單中隨機選擇一個服務;

  1. public class RandomRule extends AbstractLoadBalancerRule {
  2. public RandomRule() {
  3. }
  4.  
  5. @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
  6. //傳入一個負載均衡器
  7. public Server choose(ILoadBalancer lb, Object key) {
  8. if (lb == null) {
  9. return null;
  10. } else {
  11. Server server = null;
  12. while(server == null) {
  13. if (Thread.interrupted()) {
  14. return null;
  15. }
  16. //通過負載均衡器獲取對應的服務列表
  17. List<Server> upList = lb.getReachableServers();
  18. //通過負載均衡器獲取全部服務列表
  19. List<Server> allList = lb.getAllServers();
  20. int serverCount = allList.size();
  21. if (serverCount == 0) {
  22. return null;
  23. }
  24. //獲取一個隨機數(shù)
  25. int index = this.chooseRandomInt(serverCount);
  26. //通過這個隨機數(shù)從列表里獲取服務
  27. server = (Server)upList.get(index);
  28. if (server == null) {
  29. //當前線程轉為就緒狀態(tài),讓出cpu
  30. Thread.yield();
  31. } else {
  32. if (server.isAlive()) {
  33. return server;
  34. }
  35.  
  36. server = null;
  37. Thread.yield();
  38. }
  39. }
  40.  
  41. return server;
  42. }
  43. }

小結:通過獲取到的所有服務的數(shù)量,以這個數(shù)量為標準獲取一個(0,服務數(shù)量)的數(shù)作為獲取服務實例的下標,從而獲取到服務實例

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

  1. public class ClientConfigEnabledRoundRobinRule extends AbstractLoadBalancerRule {
  2. //使用“4”中的RoundRobinRule策略
  3. RoundRobinRule roundRobinRule = new RoundRobinRule();
  4.  
  5. public ClientConfigEnabledRoundRobinRule() {
  6. }
  7.  
  8. public void initWithNiwsConfig(IClientConfig clientConfig) {
  9. this.roundRobinRule = new RoundRobinRule();
  10. }
  11.  
  12. public void setLoadBalancer(ILoadBalancer lb) {
  13. super.setLoadBalancer(lb);
  14. this.roundRobinRule.setLoadBalancer(lb);
  15. }
  16.  
  17. public Server choose(Object key) {
  18. if (this.roundRobinRule != null) {
  19. return this.roundRobinRule.choose(key);
  20. } else {
  21. throw new IllegalArgumentException("This class has not been initialized with the RoundRobinRule class");
  22. }
  23. }
  24. }

小結:用來作為父類,子類通過實現(xiàn)它來實現(xiàn)一些高級負載均衡策略

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

  1. public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule {
  2. //注入負載均衡器,它可以選擇服務實例
  3. private LoadBalancerStats loadBalancerStats;
  4.  
  5. public BestAvailableRule() {
  6. }
  7.  
  8. public Server choose(Object key) {
  9. //假如負載均衡器實例為空,采用它父類的負載均衡機制,也就是輪詢機制,因為它的父類采用的就是輪詢機制
  10. if (this.loadBalancerStats == null) {
  11. return super.choose(key);
  12. } else {
  13. //獲取所有服務實例并放入列表里
  14. List<Server> serverList = this.getLoadBalancer().getAllServers();
  15. //并發(fā)量
  16. int minimalConcurrentConnections = 2147483647;
  17. long currentTime = System.currentTimeMillis();
  18. Server chosen = null;
  19. Iterator var7 = serverList.iterator();
  20. //遍歷服務列表
  21. while(var7.hasNext()) {
  22. Server server = (Server)var7.next();
  23. ServerStats serverStats = this.loadBalancerStats.getSingleServerStat(server);
  24. //淘汰掉已經負載的服務實例
  25. if (!serverStats.isCircuitBreakerTripped(currentTime)) {
  26. //獲得當前服務的請求量(并發(fā)量)
  27. int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
  28. //找出并發(fā)了最小的服務
  29. if (concurrentConnections < minimalConcurrentConnections) {
  30. minimalConcurrentConnections = concurrentConnections;
  31. chosen = server;
  32. }
  33. }
  34. }
  35.  
  36. if (chosen == null) {
  37. return super.choose(key);
  38. } else {
  39. return chosen;
  40. }
  41. }
  42. }
  43.  
  44. public void setLoadBalancer(ILoadBalancer lb) {
  45. super.setLoadBalancer(lb);
  46. if (lb instanceof AbstractLoadBalancer) {
  47. this.loadBalancerStats = ((AbstractLoadBalancer)lb).getLoadBalancerStats();
  48. }
  49.  
  50. }
  51. }

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

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

  1. public abstract class PredicateBasedRule extends ClientConfigEnabledRoundRobinRule {
  2. public PredicateBasedRule() {
  3. }
  4. //獲取AbstractServerPredicate對象
  5. public abstract AbstractServerPredicate getPredicate();
  6.  
  7. public Server choose(Object key) {
  8. //獲取當前策略的負載均衡器
  9. ILoadBalancer lb = this.getLoadBalancer();
  10. //通過AbstractServerPredicate的子類過濾掉一部分實例(它實現(xiàn)了Predicate)
  11. //以輪詢的方式從過濾后的服務里選擇一個服務
  12. Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
  13. return server.isPresent() ? (Server)server.get() : null;
  14. }
  15. }

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

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

是這樣的,先通過this.getEligibleServers(servers, loadBalancerKey)方法獲取一部分實例,然后判斷這部分實例是否為空,如果不為空則調用eligible.get(this.incrementAndGetModulo(eligible.size())方法從這部分實例里獲取一個服務,點進this.getEligibleServers看

  1. public List<Server> getEligibleServers(List<Server> servers, Object loadBalancerKey) {
  2. if (loadBalancerKey == null) {
  3. return ImmutableList.copyOf(Iterables.filter(servers, this.getServerOnlyPredicate()));
  4. } else {
  5. List<Server> results = Lists.newArrayList();
  6. Iterator var4 = servers.iterator();
  7.  
  8. while(var4.hasNext()) {
  9. Server server = (Server)var4.next();
  10. //條件滿足
  11. if (this.apply(new PredicateKey(loadBalancerKey, server))) {
  12. //添加到集合里
  13. results.add(server);
  14. }
  15. }
  16.  
  17. return results;
  18. }
  19. }

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

詳解SpringCloud的負載均衡

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

  1. private int incrementAndGetModulo(int modulo) {
  2. //當前下標
  3. int current;
  4. //下一個下標
  5. int next;
  6. do {
  7. //獲得當前下標值
  8. current = this.nextIndex.get();
  9. next = (current + 1) % modulo;
  10. } while(!this.nextIndex.compareAndSet(current, next) || current >= modulo);
  11.  
  12. return current;
  13. }

源碼擼明白了,再來理一下chooseRoundRobinAfterFiltering()的思路:先通過getEligibleServers()方法獲得一部分服務實例,再從這部分服務實例里拿到當前服務實例的下一個服務對象使用。

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

3.RetryRule:是對選定的負載均衡策略加上重試機制,即在一個配置好的時間段內(默認500ms),當選擇實例不成功,則一直嘗試使用subRule的方式選擇一個可用的實例,在調用時間到達閥值的時候還沒找到可用服務,則返回空,如果沒有配置負載策略,默認輪詢(即“4”中的輪詢);

先貼上它的源碼

  1. public class RetryRule extends AbstractLoadBalancerRule {
  2. //從這可以看出,默認使用輪詢機制
  3. IRule subRule = new RoundRobinRule();
  4. //500秒的閥值
  5. long maxRetryMillis = 500L;
  6. //無參構造函數(shù)
  7. public RetryRule() {
  8. }
  9. //使用輪詢機制
  10. public RetryRule(IRule subRule) {
  11. this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
  12. }
  13.  
  14. public RetryRule(IRule subRule, long maxRetryMillis) {
  15. this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
  16. this.maxRetryMillis = maxRetryMillis > 0L ? maxRetryMillis : 500L;
  17. }
  18.  
  19. public void setRule(IRule subRule) {
  20. this.subRule = (IRule)(subRule != null ? subRule : new RoundRobinRule());
  21. }
  22.  
  23. public IRule getRule() {
  24. return this.subRule;
  25. }
  26. //設置最大耗時時間(閥值),最多重試多久
  27. public void setMaxRetryMillis(long maxRetryMillis) {
  28. if (maxRetryMillis > 0L) {
  29. this.maxRetryMillis = maxRetryMillis;
  30. } else {
  31. this.maxRetryMillis = 500L;
  32. }
  33.  
  34. }
  35. //獲取重試的時間
  36. public long getMaxRetryMillis() {
  37. return this.maxRetryMillis;
  38. }
  39. //設置負載均衡器,用以獲取服務
  40. public void setLoadBalancer(ILoadBalancer lb) {
  41. super.setLoadBalancer(lb);
  42. this.subRule.setLoadBalancer(lb);
  43. }
  44. //通過負載均衡器選擇服務
  45. public Server choose(ILoadBalancer lb, Object key) {
  46. long requestTime = System.currentTimeMillis();
  47. //當前時間+閥值 = 截止時間
  48. long deadline = requestTime + this.maxRetryMillis;
  49. Server answer = null;
  50. answer = this.subRule.choose(key);
  51. //獲取到服務直接返回
  52. if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline) {
  53. InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());
  54. //獲取不到服務的情況下反復獲取
  55. while(!Thread.interrupted()) {
  56. answer = this.subRule.choose(key);
  57. if (answer != null && answer.isAlive() || System.currentTimeMillis() >= deadline) {
  58. break;
  59. }
  60.  
  61. Thread.yield();
  62. }
  63.  
  64. task.cancel();
  65. }
  66.  
  67. return answer != null && answer.isAlive() ? answer : null;
  68. }
  69.  
  70. public Server choose(Object key) {
  71. return this.choose(this.getLoadBalancer(), key);
  72. }
  73.  
  74. public void initWithNiwsConfig(IClientConfig clientConfig) {
  75. }
  76. }

小結:采用RoundRobinRule的選擇機制,進行反復嘗試,當花費時間超過設置的閾值maxRetryMills時,就返回null

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

  1. public class RoundRobinRule extends AbstractLoadBalancerRule {
  2. private AtomicInteger nextServerCyclicCounter;
  3. private static final boolean AVAILABLE_ONLY_SERVERS = true;
  4. private static final boolean ALL_SERVERS = false;
  5. private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);
  6.  
  7. public RoundRobinRule() {
  8. this.nextServerCyclicCounter = new AtomicInteger(0);
  9. }
  10.  
  11. public RoundRobinRule(ILoadBalancer lb) {
  12. this();
  13. this.setLoadBalancer(lb);
  14. }
  15.  
  16. public Server choose(ILoadBalancer lb, Object key) {
  17. if (lb == null) {
  18. log.warn("no load balancer");
  19. return null;
  20. } else {
  21. Server server = null;
  22. int count = 0;
  23.  
  24. while(true) {
  25. //選擇十次,十次都沒選到可用服務就返回空
  26. if (server == null && count++ < 10) {
  27. List<Server> reachableServers = lb.getReachableServers();
  28. List<Server> allServers = lb.getAllServers();
  29. int upCount = reachableServers.size();
  30. int serverCount = allServers.size();
  31. if (upCount != 0 && serverCount != 0) {
  32. int nextServerIndex = this.incrementAndGetModulo(serverCount);
  33. server = (Server)allServers.get(nextServerIndex);
  34. if (server == null) {
  35. Thread.yield();
  36. } else {
  37. if (server.isAlive() && server.isReadyToServe()) {
  38. return server;
  39. }
  40.  
  41. server = null;
  42. }
  43. continue;
  44. }
  45.  
  46. log.warn("No up servers available from load balancer: " + lb);
  47. return null;
  48. }
  49.  
  50. if (count >= 10) {
  51.  
  52. log.warn("No available alive servers after 10 tries from load balancer: " + lb);
  53. }
  54.  
  55. return server;
  56. }
  57. }
  58. }
  59.  
  60. //遞增的形式實現(xiàn)輪詢
  61. private int incrementAndGetModulo(int modulo) {
  62. int current;
  63. int next;
  64. do {
  65. current = this.nextServerCyclicCounter.get();
  66. next = (current + 1) % modulo;
  67. } while(!this.nextServerCyclicCounter.compareAndSet(current, next));
  68.  
  69. return next;
  70. }
  71.  
  72. public Server choose(Object key) {
  73. return this.choose(this.getLoadBalancer(), key);
  74. }
  75.  
  76. public void initWithNiwsConfig(IClientConfig clientConfig) {
  77. }
  78. }

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

它有個子類WeightedResponseTimeRule,WeightedResponseTimeRule是對RoundRobinRule的優(yōu)化。WeightedResponseTimeRule在其父類的基礎上,增加了定時任務這個功能,通過啟動一個定時任務來計算每個服務的權重,然后遍歷服務列表選擇服務實例,從而達到更加優(yōu)秀的分配效果。我們這里把這個類分為三部分:定時任務,計算權值,選擇服務

1)定時任務

  1. //定時任務
  2. void initialize(ILoadBalancer lb) {
  3. if (this.serverWeightTimer != null) {
  4. this.serverWeightTimer.cancel();
  5. }
  6.  
  7. this.serverWeightTimer = new Timer("NFLoadBalancer-serverWeightTimer-" + this.name, true);
  8. //開啟一個任務,每30秒執(zhí)行一次
  9. this.serverWeightTimer.schedule(new WeightedResponseTimeRule.DynamicServerWeightTask(), 0L, (long)this.serverWeightTaskTimerInterval);
  10. WeightedResponseTimeRule.ServerWeight sw = new WeightedResponseTimeRule.ServerWeight();
  11. sw.maintainWeights();
  12. Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
  13. public void run() {
  14. WeightedResponseTimeRule.logger.info("Stopping NFLoadBalancer-serverWeightTimer-" + WeightedResponseTimeRule.this.name);
  15. WeightedResponseTimeRule.this.serverWeightTimer.cancel();
  16. }
  17. }));
  18. }

DynamicServerWeightTask()任務如下:

  1. class DynamicServerWeightTask extends TimerTask {
  2. DynamicServerWeightTask() {
  3. }
  4.  
  5. public void run() {
  6. WeightedResponseTimeRule.ServerWeight serverWeight = WeightedResponseTimeRule.this.new ServerWeight();
  7.  
  8. try {
  9. //計算權重
  10. serverWeight.maintainWeights();
  11. } catch (Exception var3) {
  12. WeightedResponseTimeRule.logger.error("Error running DynamicServerWeightTask for {}", WeightedResponseTimeRule.this.name, var3);
  13. }
  14.  
  15. }
  16. }

小結:調用initialize方法開啟定時任務,再在任務里計算服務的權重

2)計算權重:第一步,先算出所有實例的響應時間;第二步,再根據(jù)所有實例響應時間,算出每個實例的權重

  1. //用來存儲權重
  2. private volatile List<Double> accumulatedWeights = new ArrayList();
  3.  
  4. //內部類
  5. class ServerWeight {
  6. ServerWeight() {
  7. }
  8. //該方法用于計算權重
  9. public void maintainWeights() {
  10. //獲取負載均衡器
  11. ILoadBalancer lb = WeightedResponseTimeRule.this.getLoadBalancer();
  12. if (lb != null) {
  13. if (WeightedResponseTimeRule.this.serverWeightAssignmentInProgress.compareAndSet(false, true)) {
  14. try {
  15. WeightedResponseTimeRule.logger.info("Weight adjusting job started");
  16. AbstractLoadBalancer nlb = (AbstractLoadBalancer)lb;
  17. //獲得每個服務實例的信息
  18. LoadBalancerStats stats = nlb.getLoadBalancerStats();
  19. if (stats != null) {
  20. //實例的響應時間
  21. double totalResponseTime = 0.0D;
  22.  
  23. ServerStats ss;
  24. //累加所有實例的響應時間
  25. for(Iterator var6 = nlb.getAllServers().iterator(); var6.hasNext(); totalResponseTime += ss.getResponseTimeAvg()) {
  26. Server server = (Server)var6.next();
  27. ss = stats.getSingleServerStat(server);
  28. }
  29.  
  30. Double weightSoFar = 0.0D;
  31. List<Double> finalWeights = new ArrayList();
  32. Iterator var20 = nlb.getAllServers().iterator();
  33. //計算負載均衡器所有服務的權重,公式是weightSoFar = weightSoFar + weight-實例平均響應時間
  34. while(var20.hasNext()) {
  35. Server serverx = (Server)var20.next();
  36. ServerStats ssx = stats.getSingleServerStat(serverx);
  37. double weight = totalResponseTime - ssx.getResponseTimeAvg();
  38. weightSoFar = weightSoFar + weight;
  39. finalWeights.add(weightSoFar);
  40. }
  41.  
  42. WeightedResponseTimeRule.this.setWeights(finalWeights);
  43. return;
  44. }
  45. } catch (Exception var16) {
  46. WeightedResponseTimeRule.logger.error("Error calculating server weights", var16);
  47. return;
  48. } finally {
  49. WeightedResponseTimeRule.this.serverWeightAssignmentInProgress.set(false);
  50. }
  51.  
  52. }
  53. }
  54. }
  55. }

3)選擇服務

  1. @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
  2. public Server choose(ILoadBalancer lb, Object key) {
  3. if (lb == null) {
  4. return null;
  5. } else {
  6. Server server = null;
  7.  
  8. while(server == null) {
  9. List<Double> currentWeights = this.accumulatedWeights;
  10. if (Thread.interrupted()) {
  11. return null;
  12. }
  13.  
  14. List<Server> allList = lb.getAllServers();
  15. int serverCount = allList.size();
  16. if (serverCount == 0) {
  17. return null;
  18. }
  19.  
  20. int serverIndex = 0;
  21.  
  22. double maxTotalWeight = currentWeights.size() == 0 ? 0.0D : (Double)currentWeights.get(currentWeights.size() - 1);
  23. if (maxTotalWeight >= 0.001D && serverCount == currentWeights.size()) {
  24. //生產0到最大權重值的隨機數(shù)
  25. double randomWeight = this.random.nextDouble() * maxTotalWeight;
  26. int n = 0;
  27. //循環(huán)權重區(qū)間
  28. for(Iterator var13 = currentWeights.iterator(); var13.hasNext(); ++n) {
  29. //獲取到循環(huán)的數(shù)
  30. Double d = (Double)var13.next();
  31. //假如隨機數(shù)在這個區(qū)間內,就拿該索引d服務列表獲取對應的實例
  32. if (d >= randomWeight) {
  33. serverIndex = n;
  34. break;
  35. }
  36. }
  37.  
  38. server = (Server)allList.get(serverIndex);
  39. } else {
  40. server = super.choose(this.getLoadBalancer(), key);
  41. if (server == null) {
  42. return server;
  43. }
  44. }
  45.  
  46. if (server == null) {
  47. Thread.yield();
  48. } else {
  49. if (server.isAlive()) {
  50. return server;
  51. }
  52.  
  53. server = null;
  54. }
  55. }
  56.  
  57. return server;
  58. }
  59. }

小結:首先生成了一個[0,最大權重值) 區(qū)間內的隨機數(shù),然后遍歷權重列表,假如當前隨機數(shù)在這個區(qū)間內,就通過該下標獲得對應的服務。

以上就是詳解SpringCloud的負載均衡的詳細內容,更多關于SpringCloud 負載均衡的資料請關注服務器之家其它相關文章!

原文鏈接:https://www.cnblogs.com/fengrongriup/p/14505755.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩成人免费 | 男人操美女视频 | 69av导航 | 天堂色 | 国产免费大片 | 俄罗斯一级在线播放 | 久久伊人在 | 花核调教 | 99久精品 | 99在线观看视频免费精品9 | 99福利在线观看 | 日本在线亚州精品视频在线 | 国产精品视频播放 | wankz视频| 色综合天天综合网看在线影院 | 性夜a爽黄爽| 99热er| 国产精品99在线观看 | 98成人网| 暴露狂婷婷医院暴露tx | 亚洲精品久久碰 | 欧洲男同直粗无套播放视频 | 91免费视频国产 | 91精品手机国产露脸 | 天天躁天天碰天天看 | 亚洲免费网站在线观看 | 欧美日韩一区二区三区久久 | 天天操天天射天天色 | 欧美在线观看一区二区三 | 91av俱乐部 | 日韩porn| 任你操视频在线观看 | 闺蜜调教我做她的脚奴 | 4虎影视国产在线观看精品 4s4s4s4s色大众影视 | 冰漪丰满大乳人体图片欣赏 | 国产宅男 | 免费av在线看 | 久久久久999 | 国产伦精品一区二区三区女 | 日韩一级免费毛片 | 精品女同一区二区三区免费站 |