详解SpringCloud的负载均衡

目录
  • 一.什么是负载均衡
  • 二.负载均衡的简单分类
  • 三.为什么需要做负载均衡
  • 四.springCloud如何开启负载均衡
  • 五.IRule
    • 1.RandomRule:表示随机策略,它将从服务清单中随机选择一个服务;
    • 2.ClientConfigEnabledRoundRobinRule:ClientConfigEnabledRoundRobinRule并没有实现什么特殊的处理逻辑,但是他的子类可以实现一些高级策略, 当一些本身的策略无法实现某些需求的时候,它也可以做为父类帮助实现某些策略,一般情况下我们都不会使用它;
    • 3.RetryRule:是对选定的负载均衡策略加上重试机制,即在一个配置好的时间段内(默认500ms),当选择实例不成功,则一直尝试使用subRule的方式选择一个可用的实例,在调用时间到达阀值的时候还没找到可用服务,则返回空,如果没有配置负载策略,默认轮询(即“4”中的轮询);
    • 4.RoundRobinRule:轮询策略,它会从服务清单中按照轮询的方式依次选择每个服务实例,它的工作原理是:直接获取下一个可用实例,如果超过十次没有获取到可用的服务实例,则返回空且报出异常信息;

一.什么是负载均衡

负载均衡(Load-balance LB),指的是将用户的请求平摊分配到各个服务器上,从而达到系统的高可用。常见的负载均衡软件有Nginx、lvs等。

二.负载均衡的简单分类

1)集中式LB:集中式负载均衡指的是,在服务消费者(client)和服务提供者(provider)之间提供负载均衡设施,通过该设施把消费者(client)的请求通过某种策略转发给服务提供者(provider),常见的集中式负载均衡是Nginx;

2)进程式LB:将负载均衡的逻辑集成到消费者(client)身上,即消费者从服务注册中心获取服务列表,获知有哪些地址可用,再从这些地址里选出合适的服务器,springCloud的Ribbon就是一个进程式的负载均衡工具。

三.为什么需要做负载均衡

1) 不做负载均衡,可能导致某台机子负荷太重而挂掉;

2)导致资源浪费,比如某些机子收到太多的请求,肯定会导致某些机子收到很少请求甚至收不到请求,这样会浪费系统资源。

四.springCloud如何开启负载均衡

1)在消费者子工程的pom.xml文件的加入相关依赖(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>

消费者需要获取服务注册中心的注册列表信息,把Eureka的依赖包也放进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里配置服务注册中心的信息

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

#配置Eureka
eureka:
 client:
 #是否注册自己到服务注册中心,消费者不用提供服务
 register-with-eureka: false
 service-url:
  #访问的url
  defaultZone: http://localhost:8002/eureka/

3)在消费者启动类上面加上注解@EnableEurekaClient

@EnableEurekaClient

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

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

五.IRule

什么是IRule

IRule接口代表负载均衡的策略,它的不同的实现类代表不同的策略,它的四种实现类和它的关系如下()

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

1.RandomRule:表示随机策略,它将从服务清单中随机选择一个服务;

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

 @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) {
    if (Thread.interrupted()) {
     return null;
    }
    //通过负载均衡器获取对应的服务列表
    List<Server> upList = lb.getReachableServers();
    //通过负载均衡器获取全部服务列表
    List<Server> allList = lb.getAllServers();
    int serverCount = allList.size();
    if (serverCount == 0) {
     return null;
    }
    //获取一个随机数
    int index = this.chooseRandomInt(serverCount);
    //通过这个随机数从列表里获取服务
    server = (Server)upList.get(index);
    if (server == null) {
     //当前线程转为就绪状态,让出cpu
     Thread.yield();
    } else {
     if (server.isAlive()) {
      return server;
     }

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

   return server;
  }
 }

小结:通过获取到的所有服务的数量,以这个数量为标准获取一个(0,服务数量)的数作为获取服务实例的下标,从而获取到服务实例

2.ClientConfigEnabledRoundRobinRule:ClientConfigEnabledRoundRobinRule并没有实现什么特殊的处理逻辑,但是他的子类可以实现一些高级策略, 当一些本身的策略无法实现某些需求的时候,它也可以做为父类帮助实现某些策略,一般情况下我们都不会使用它;

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");
  }
 }
}

小结:用来作为父类,子类通过实现它来实现一些高级负载均衡策略

1)ClientConfigEnabledRoundRobinRule的子类BestAvailableRule:从该策略的名字就可以知道,bestAvailable的意思是最好获取的,该策略的作用是获取到最空闲的服务实例;

public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule {
 //注入负载均衡器,它可以选择服务实例
 private LoadBalancerStats loadBalancerStats;

 public BestAvailableRule() {
 }

 public Server choose(Object key) {
  //假如负载均衡器实例为空,采用它父类的负载均衡机制,也就是轮询机制,因为它的父类采用的就是轮询机制
  if (this.loadBalancerStats == null) {
   return super.choose(key);
  } else {
   //获取所有服务实例并放入列表里
   List<Server> serverList = this.getLoadBalancer().getAllServers();
   //并发量
   int minimalConcurrentConnections = 2147483647;
   long currentTime = System.currentTimeMillis();
   Server chosen = null;
   Iterator var7 = serverList.iterator();
   //遍历服务列表
   while(var7.hasNext()) {
    Server server = (Server)var7.next();
    ServerStats serverStats = this.loadBalancerStats.getSingleServerStat(server);
    //淘汰掉已经负载的服务实例
    if (!serverStats.isCircuitBreakerTripped(currentTime)) {
     //获得当前服务的请求量(并发量)
     int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
     //找出并发了最小的服务
     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();
  }

 }
}

小结:ClientConfigEnabledRoundRobinRule子类之一,获取到并发了最少的服务

2)ClientConfigEnabledRoundRobinRule的另一个子类是PredicateBasedRule:通过源码可以看出它是一个抽象类,它的抽象方法getPredicate()返回一个AbstractServerPredicate的实例,然后它的choose方法调用AbstractServerPredicate类的chooseRoundRobinAfterFiltering方法获取具体的Server实例并返回

public abstract class PredicateBasedRule extends ClientConfigEnabledRoundRobinRule {
 public PredicateBasedRule() {
 }
 //获取AbstractServerPredicate对象
 public abstract AbstractServerPredicate getPredicate();

 public Server choose(Object key) {
  //获取当前策略的负载均衡器
  ILoadBalancer lb = this.getLoadBalancer();
  //通过AbstractServerPredicate的子类过滤掉一部分实例(它实现了Predicate)
  //以轮询的方式从过滤后的服务里选择一个服务
  Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
  return server.isPresent() ? (Server)server.get() : null;
 }
}

再看看它的chooseRoundRobinAfterFiltering()方法是如何实现的

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())));
 }

是这样的,先通过this.getEligibleServers(servers, loadBalancerKey)方法获取一部分实例,然后判断这部分实例是否为空,如果不为空则调用eligible.get(this.incrementAndGetModulo(eligible.size())方法从这部分实例里获取一个服务,点进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方法是根据this.apply(new PredicateKey(loadBalancerKey, server))进行过滤的,如果满足,就添加到返回的集合中。符合什么条件才可以进行过滤呢?可以发现,apply是用this调用的,this指的是AbstractServerPredicate(它的类对象),但是,该类是个抽象类,该实例是不存在的,需要子类去实现,它的子类在这里暂时不是看了,以后有空再深入学习下,它的子类如下,实现哪个子类,就用什么 方式过滤。

再回到chooseRoundRobinAfterFiltering()方法,刚刚说完它通过 getEligibleServers方法过滤并获取到一部分实例,然后再通过this.incrementAndGetModulo(eligible.size())方法从这部分实例里选择一个实例返回,该方法的意思是直接返回下一个整数(索引值),通过该索引值从返回的实例列表中取得Server实例。

private int incrementAndGetModulo(int modulo) {
  //当前下标
  int current;
  //下一个下标
  int next;
  do {
   //获得当前下标值
   current = this.nextIndex.get();
   next = (current + 1) % modulo;
  } while(!this.nextIndex.compareAndSet(current, next) || current >= modulo);

  return current;
 }

源码撸明白了,再来理一下chooseRoundRobinAfterFiltering()的思路:先通过getEligibleServers()方法获得一部分服务实例,再从这部分服务实例里拿到当前服务实例的下一个服务对象使用。

小结:通过AbstractServerPredicate的chooseRoundRobinAfterFiltering方法进行过滤,获取备选的服务实例清单,然后用线性轮询选择一个实例,是一个抽象类,过滤策略在AbstractServerPredicate的子类中具体实现

3.RetryRule:是对选定的负载均衡策略加上重试机制,即在一个配置好的时间段内(默认500ms),当选择实例不成功,则一直尝试使用subRule的方式选择一个可用的实例,在调用时间到达阀值的时候还没找到可用服务,则返回空,如果没有配置负载策略,默认轮询(即“4”中的轮询);

先贴上它的源码

public class RetryRule extends AbstractLoadBalancerRule {
 //从这可以看出,默认使用轮询机制
 IRule subRule = new RoundRobinRule();
 //500秒的阀值
 long maxRetryMillis = 500L;
 //无参构造函数
 public RetryRule() {
 }
 //使用轮询机制
 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;
 }
 //设置最大耗时时间(阀值),最多重试多久
 public void setMaxRetryMillis(long maxRetryMillis) {
  if (maxRetryMillis > 0L) {
   this.maxRetryMillis = maxRetryMillis;
  } else {
   this.maxRetryMillis = 500L;
  }

 }
 //获取重试的时间
 public long getMaxRetryMillis() {
  return this.maxRetryMillis;
 }
 //设置负载均衡器,用以获取服务
 public void setLoadBalancer(ILoadBalancer lb) {
  super.setLoadBalancer(lb);
  this.subRule.setLoadBalancer(lb);
 }
 //通过负载均衡器选择服务
 public Server choose(ILoadBalancer lb, Object key) {
  long requestTime = System.currentTimeMillis();
  //当前时间+阀值 = 截止时间
  long deadline = requestTime + this.maxRetryMillis;
  Server answer = null;
  answer = this.subRule.choose(key);
  //获取到服务直接返回
  if ((answer == null || !answer.isAlive()) && System.currentTimeMillis() < deadline) {
   InterruptTask task = new InterruptTask(deadline - System.currentTimeMillis());
   //获取不到服务的情况下反复获取
   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) {
 }
}

小结:采用RoundRobinRule的选择机制,进行反复尝试,当花费时间超过设置的阈值maxRetryMills时,就返回null

4.RoundRobinRule:轮询策略,它会从服务清单中按照轮询的方式依次选择每个服务实例,它的工作原理是:直接获取下一个可用实例,如果超过十次没有获取到可用的服务实例,则返回空且报出异常信息;

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) {
    //选择十次,十次都没选到可用服务就返回空
    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;
   }
  }
 }

 //递增的形式实现轮询
 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) {
 }
}

小结:采用线性轮询机制循环依次选择每个服务实例,直到选择到一个不为空的服务实例或循环次数达到10次

它有个子类WeightedResponseTimeRule,WeightedResponseTimeRule是对RoundRobinRule的优化。WeightedResponseTimeRule在其父类的基础上,增加了定时任务这个功能,通过启动一个定时任务来计算每个服务的权重,然后遍历服务列表选择服务实例,从而达到更加优秀的分配效果。我们这里把这个类分为三部分:定时任务,计算权值,选择服务

1)定时任务

//定时任务
void initialize(ILoadBalancer lb) {
  if (this.serverWeightTimer != null) {
   this.serverWeightTimer.cancel();
  }

  this.serverWeightTimer = new Timer("NFLoadBalancer-serverWeightTimer-" + this.name, true);
  //开启一个任务,每30秒执行一次
  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()任务如下:

class DynamicServerWeightTask extends TimerTask {
  DynamicServerWeightTask() {
  }

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

   try {
    //计算权重
    serverWeight.maintainWeights();
   } catch (Exception var3) {
    WeightedResponseTimeRule.logger.error("Error running DynamicServerWeightTask for {}", WeightedResponseTimeRule.this.name, var3);
   }

  }
 }

小结:调用initialize方法开启定时任务,再在任务里计算服务的权重

2)计算权重:第一步,先算出所有实例的响应时间;第二步,再根据所有实例响应时间,算出每个实例的权重

//用来存储权重
private volatile List<Double> accumulatedWeights = new ArrayList();

//内部类
class ServerWeight {
  ServerWeight() {
  }
  //该方法用于计算权重
  public void maintainWeights() {
   //获取负载均衡器
   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;
      //获得每个服务实例的信息
      LoadBalancerStats stats = nlb.getLoadBalancerStats();
      if (stats != null) {
       //实例的响应时间
       double totalResponseTime = 0.0D;

       ServerStats ss;
       //累加所有实例的响应时间
       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();
       //计算负载均衡器所有服务的权重,公式是weightSoFar = weightSoFar + weight-实例平均响应时间
       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)选择服务

@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()) {
     //生产0到最大权重值的随机数
     double randomWeight = this.random.nextDouble() * maxTotalWeight;
     int n = 0;
     //循环权重区间
     for(Iterator var13 = currentWeights.iterator(); var13.hasNext(); ++n) {
      //获取到循环的数
      Double d = (Double)var13.next();
      //假如随机数在这个区间内,就拿该索引d服务列表获取对应的实例
      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;
  }
 }

小结:首先生成了一个[0,最大权重值) 区间内的随机数,然后遍历权重列表,假如当前随机数在这个区间内,就通过该下标获得对应的服务。

以上就是详解SpringCloud的负载均衡的详细内容,更多关于SpringCloud 负载均衡的资料请关注我们其它相关文章!

(0)

相关推荐

  • SpringCloud客户端的负载均衡Ribbon的实现

    前言:微服务架构,不可避免的存在单个微服务有多个实例,那么客户端如何将请求分摊到多个微服务的实例上呢?这里我们就需要使用负载均衡了 一.Ribbon简介 Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为.为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求.Ribbon默认为我们提供了很多的负载均衡算法,例如:轮询,随机等,也可自定义: Ribbon的GitHub: https://github.com/N

  • SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法

    1.Ribbon Spring Cloud Ribbon是基于Netflix Ribbon实现的-套客户端―负载均衡的工具. 简单的说,Ribbon是Netlix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用.Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等.简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器.我们很容易使用Ribbon实现自定义的负载均

  • SpringCloud与Consul集成实现负载均衡功能

    负载均衡(Load Balance,简称LB)是一种服务器或网络设备的集群技术.负载均衡将特定的业务(网络服务.网络流量等)分担给多个服务器或网络设备,从而提高了业务处理能力,保证了业务的高可用性.负载均衡基本概念有:实服务.实服务组.虚服务.调度算法.持续性等,其常用应用场景主要是服务器负载均衡,链路负载均衡. 一.背景 SpringCloud微服务目前比较流行,其中大都在使用的服务注册与发现是Eureka,最近研究了Consul的集群搭建,现使用Consul实现服务的负载均衡.其主要拓扑结构

  • SpringCloud Ribbon负载均衡实例解析

    这篇文章主要介绍了SpringCloud Ribbon负载均衡实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring Cloud集成了Ribbon,结合Eureka,可实现客户端的负载均衡. 下面实现一个例子,结构下图所示. 一.服务器端 1.创建项目 开发工具:IntelliJ IDEA 2019.2.3 IDEA中创建一个新的SpringBoot项目,名称为"cloud-server",SpringBoot版本选择2

  • SpringCloud Ribbon负载均衡代码实例

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId&g

  • SpringCloud手写Ribbon实现负载均衡

    前言 前面我们学习了 SpringCloud整合Consul,在此基础上我们手写本地客户端实现类似Ribbon负载均衡的效果. 注: order 模块调用者 记得关闭 @LoadBalanced 注解. 我们这里只演示 注册中心 consul,至于 zookeeper 也是一模一样. 生产者 member模块 member 服务需要集群,所以我们copy application-consul.yml 文件命名为 application-consul2.yml 服务别名一致,只需要修改端口号即可.

  • SpringCloud Ribbon 负载均衡的实现

    前言 Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制.我们在上篇(猛戳:SpringCloud系列--Feign 服务调用)已经实现了多个服务之间的Feign调用,服务消费者调用服务提供者,本文记录Feign调用Ribbon负载均衡的服务提供者 GitHub地址:https://github.com/Netflix/ribbon 官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-net

  • 详解SpringCloud Ribbon 负载均衡通过服务器名无法连接的神坑

    一,问题 采取eureka集群.客户端通过Ribbon调用服务,Ribbon端报下列异常 java.net.UnknownHostException: SERVICE-HI java.lang.IllegalStateException: No instances available for SERVICE-HI java.lang.IllegalStateException: Request URI does not contain a valid hostname: http://SERVI

  • Springcloud ribbon负载均衡算法实现

    一 前言 经过几篇的cloud系列文章,我想大家都有一个坚实的基础,后续的学习就会轻松很多,如果是刚刚来看的读者需要有eureka基础知识,或者查阅知识追寻者的cloud系列专栏:这篇文章主要讲解如何使用ribbon实现web service客户端调用,ribbon默认算法实现负载均衡等! 二 ribbon简介 ribbon是一个客户端负载均衡器,其能够整合不同的协议工具进行web service API 调用: 主要特色如下: 提供可插拔式的负载均衡整合服务发现故障弹性恢复cloud支持客户端

  • 详解SpringCloud的负载均衡

    目录 一.什么是负载均衡 二.负载均衡的简单分类 三.为什么需要做负载均衡 四.springCloud如何开启负载均衡 五.IRule 1.RandomRule:表示随机策略,它将从服务清单中随机选择一个服务: 2.ClientConfigEnabledRoundRobinRule:ClientConfigEnabledRoundRobinRule并没有实现什么特殊的处理逻辑,但是他的子类可以实现一些高级策略, 当一些本身的策略无法实现某些需求的时候,它也可以做为父类帮助实现某些策略,一般情况下

  • 详解.NET中负载均衡的使用

    目录 一.简介 二.应用场景 三.实际案例 四.算法实现 4.1 随机 4.2 轮询 4.3 权重 一.简介 负载均衡(Load Balance),简称 LB,就是将并发的用户请求通过规则后平衡.分摊到多台服务器上进行执行,以此达到压力分摊.数据并行的效果.常见的算法也有许多随机.轮询.加权等,今天我们就使用 C# 来实现这几种算法,并讲解在实际项目中的使用. 二.应用场景 负载均衡算法在开发层面,使用场景其实并不多.通常在项目重构.转型.上线大版本新功能等,为了避免上线出现 Bug 应用功能

  • 详解Nginx HTTP负载均衡和反向代理配置

    当前大并发的网站基本都采用了Nginx来做代理服务器,并且做缓存,来扛住大并发.先前也用nginx配置过简单的代理,今天有时间把整合过程拿出来和大家分享,不过其中大部分也是网上找来的资源. nginx完整的反向代理代码如下所示  : [root@data conf]# vim nginx.conf user www www; worker_processes 10; error_log /var/log/nginx/nginx_error.log; pid logs/nginx.pid; wor

  • 详解Java实现负载均衡的几种算法代码

    本篇文章主要介绍Java实现负载均衡的几种算法,具体如下: 轮询: package class2.zookeeper.loadbalance; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 負載均衡算法,輪詢法 * @author guoy * */ public class TestRoundRobin { static Map<St

  • 详解Spring Cloud负载均衡重要组件Ribbon中重要类的用法

    Ribbon是Spring Cloud Netflix全家桶中负责负载均衡的组件,它是一组类库的集合.通过Ribbon,程序员能在不涉及到具体实现细节的基础上"透明"地用到负载均衡,而不必在项目里过多地编写实现负载均衡的代码. 比如,在某个包含Eureka和Ribbon的集群中,某个服务(可以理解成一个jar包)被部署在多台服务器上,当多个服务使用者同时调用该服务时,这些并发的请求能被用一种合理的策略转发到各台服务器上. 事实上,在使用Spring Cloud的其它各种组件时,我们都能

  • 详解SpringCloud服务认证(JWT)

     - JWT JWT(JSON Web Token), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景.JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密. - JWT与其它的区别 通常情况下,把API直接暴露出去是风险很大的,不说别的

  • SpringCloud 2020-Ribbon负载均衡服务调用的实现

    1.概述 官网:https://github.com/Netflix/ribbon/wiki/Getting-Started Ribbon目前也进入维护模式,未来替换方案: LB(负载均衡) 集中式LB 进程内LB Ribbon就是负载均衡+RestTemplate调用 2.Ribbon负载均衡演示 1.架构说明 总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例. 2. 3.二说RestTemplate的使用 官网

随机推荐