Netflix中的负载均衡策略

Spring Cloud的负载均衡策略可以通过配置Ribbon搞定,也就是注入实现com.netflix.loadbalancer.IRule的类,当前包含的策略包括

1.RandomRule 随机策略 在while循环内,如果服务地址不为空会不停的循环直到随机出一个可用的服务。

@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.rand.nextInt(serverCount);
                server = (Server)upList.get(index);
                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

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

            return server;
        }
    }

不过感觉怎么第一个就有坑呢。。upList表示当前可用的服务实例集合,这个集合可以由客户端开启定时任务定期对调用服务进行ping来更新,allList表示当前所有服务实例的集合。

也就是说当存在。通过com.netflix.loadbalancer.BaseLoadBalancer中可见:

     public boolean[] pingServers(IPing ping, Server[] servers) {
            int numCandidates = servers.length;
            boolean[] results = new boolean[numCandidates];
            BaseLoadBalancer.logger.debug("LoadBalancer:  PingTask executing [{}] servers configured", numCandidates);

            for(int i = 0; i < numCandidates; ++i) {
                results[i] = false;

                try {
                    if (ping != null) {
                        results[i] = ping.isAlive(servers[i]);
                    }
                } catch (Exception var7) {
                    BaseLoadBalancer.logger.error("Exception while pinging Server: ‘{}‘", servers[i], var7);
                }
            }

            return results;
        }
     public void runPinger() throws Exception {
            if (BaseLoadBalancer.this.pingInProgress.compareAndSet(false, true)) {
                Server[] allServers = null;
                boolean[] results = null;
                Lock allLock = null;
                Lock upLock = null;

                try {
                    allLock = BaseLoadBalancer.this.allServerLock.readLock();
                    allLock.lock();
                    allServers = (Server[])BaseLoadBalancer.this.allServerList.toArray(new Server[BaseLoadBalancer.this.allServerList.size()]);
                    allLock.unlock();
                    int numCandidates = allServers.length;
                    boolean[] resultsx = this.pingerStrategy.pingServers(BaseLoadBalancer.this.ping, allServers);
                    List<Server> newUpList = new ArrayList();
                    List<Server> changedServers = new ArrayList();

                    for(int i = 0; i < numCandidates; ++i) {
                        boolean isAlive = resultsx[i];
                        Server svr = allServers[i];
                        boolean oldIsAlive = svr.isAlive();
                        svr.setAlive(isAlive);
                        if (oldIsAlive != isAlive) {
                            changedServers.add(svr);
                            BaseLoadBalancer.logger.debug("LoadBalancer [{}]:  Server [{}] status changed to {}", new Object[]{BaseLoadBalancer.this.name, svr.getId(), isAlive ? "ALIVE" : "DEAD"});
                        }

                        if (isAlive) {
                            newUpList.add(svr);
                        }
                    }

                    upLock = BaseLoadBalancer.this.upServerLock.writeLock();
                    upLock.lock();
                    BaseLoadBalancer.this.upServerList = newUpList;
                    upLock.unlock();
                    BaseLoadBalancer.this.notifyServerStatusChangeListener(changedServers);
                } finally {
                    BaseLoadBalancer.this.pingInProgress.set(false);
                }
            }
        }

如此看来,当upList数量不等于allList数量时,这个server = (Server)upList.get(index);就出问题了!?当然,默认情况下ping的方法是不进行真实健康监测的,即所有服务都是健康的,保证allList.size()=upList.size();不过感觉很怪异。

2.RoundRobinRule 轮询策略,但是有个查找次数的限制,也就是说查了10次都是不可用的服务的话就会警告没有可用服务并返回null了,选择的方式是很简单,取余运算。

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

此处的upCount依然是个摆设。。。

3.ClientConfigEnabledRoundRobinRule 默认使用RoundRobinRule 策略 不过字面意思,客户端可配置的,所以可以作为父类扩展

 public void initWithNiwsConfig(IClientConfig clientConfig) {
        this.roundRobinRule = new RoundRobinRule();
    }
    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");
        }
    }

4.WeightedResponseTimeRule 实例初始化的时候会开启一个定时任务,通过定时任务来获取服务响应时间定期维护每个服务的权重

 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)).doubleValue();
                if (maxTotalWeight < 0.001D) {
                    server = super.choose(this.getLoadBalancer(), key);
                    if (server == null) {
                        return server;
                    }
                } else {
                    double randomWeight = this.random.nextDouble() * maxTotalWeight;
                    int n = 0;

                    for(Iterator var13 = currentWeights.iterator(); var13.hasNext(); ++n) {
                        Double d = (Double)var13.next();
                        if (d.doubleValue() >= randomWeight) {
                            serverIndex = n;
                            break;
                        }
                    }

                    server = (Server)allList.get(serverIndex);
                }

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

                    server = null;
                }
            }

            return server;
        }
    }

    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()) {
  //通过ss.getResponseTimeAvg()获取每个服务的平均响应时间 然后累加到totalResponseTime中
                                Server server = (Server)var6.next();
                                ss = stats.getSingleServerStat(server);
                            }

                            Double weightSoFar = 0.0D;
                            List<Double> finalWeights = new ArrayList();
                            Iterator var20 = nlb.getAllServers().iterator();

                            while(var20.hasNext()) {
                                Server serverx = (Server)var20.next();
                                ServerStats ssx = stats.getSingleServerStat(serverx);
                                double weight = totalResponseTime - ssx.getResponseTimeAvg();//所有服务的平均响应时间的和-该服务的平均响应时间=该服务的权重
                                weightSoFar = weightSoFar.doubleValue() + weight;
//由于通过集合存储 所以此处采取区间的模式 也就是从0到n,n到...的模式
//比如 三个服务 响应时间分别为10,20,30 则权重分别为(0-50)(50-90)(90-120)
                                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);
                    }

                }
            }
        }

不过当权重的集合中没有数据的时候,这个类继承了RoundRobinRule 类,就使用轮询的方式选择了。如果存在权重信息则使用this.random.nextDouble() * maxTotalWeight的方式也就是1以内小数*最大权重值区间内的随机数来选取服务索引的方式。跟RandomRule 的模式一样,当选取的服务状态异常的时候会While循环走下去。直到。。。死循环。

5.BestAvailableRule 对所有实例进行迭代,首先过滤掉不可用的服务,然后选出连接数最少的服务返回,继承了ClientConfigEnabledRoundRobinRule类也就是使用了RoundRobinRule策略,也就是loadBalancerStats进行统计服务连接信息为空的时候先采用轮询策略过渡。

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

6.RetryRule 采用了轮询策略(内部直接实例化RoundRobinRule使用)的重试策略来获取可用的服务实例。这里有个maxRetryMillis属性用来限定重试的时间,如果首次获取服务实例为空,则开启一个定指定关闭时间的定时线程,在该指定时间内如果没有找到可用的实例就返回null了。默认为500毫秒。(轮询策略内不是10次以内不管找到可用实例与否都返回结果,所以此处可以看成一个次数微微可控的加强版)

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

7.PredicateBasedRule 继承自ClientConfigEnabledRoundRobinRule的一个抽象类。

   public abstract AbstractServerPredicate getPredicate();

    public Server choose(Object key) {
        ILoadBalancer lb = this.getLoadBalancer();
        Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
        return server.isPresent() ? (Server)server.get() : null;
    }

使用的时候需要重写getPredicate方法,目测是先过滤一部分服务然后在选择一个服务。

//上边方法this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);调用到这
  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.nextIndex.getAndIncrement() % eligible.size()));
//此处可见过滤后的集合为空则返回 Optional.absent()表示不存在对象集合(通过isPresent()方法默认就是false),集合不为空则还是如同轮询算法般取余
    }
    public List<Server> getEligibleServers(List<Server> servers, Object loadBalancerKey) {
        if (loadBalancerKey == null) {
            return ImmutableList.copyOf(Iterables.filter(servers, this.getServerOnlyPredicate()));//loadBalancerKey 如果为null的话 则返回当前即可(这个filter的过滤条件是不过滤。。。)
        } 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;
        }
    }

当然这个抽象类需要我们实现getPredicate()返回AbstractServerPredicate过滤条件(默认全部返回为true,也就是等价于采用轮询的模式了)。

8.AvailabilityFilteringRule实现PredicateBasedRule类,如代码所示,组合条件是一个new AvailabilityPredicate().

   private AbstractServerPredicate predicate = CompositePredicate.withPredicate(new AvailabilityPredicate(this, (IClientConfig)null)).addFallbackPredicate(AbstractServerPredicate.alwaysTrue()).build();
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        this.predicate = CompositePredicate.withPredicate(new AvailabilityPredicate(this, clientConfig)).addFallbackPredicate(AbstractServerPredicate.alwaysTrue()).build();
    }

查看过滤条件

    public boolean apply(@Nullable PredicateKey input) {
        LoadBalancerStats stats = this.getLBStats();
        if (stats == null) {
            return true;
        } else {
            return !this.shouldSkipServer(stats.getSingleServerStat(input.getServer()));//下边返回true则这块会把该服务实例过滤掉 返回为!true
        }
    }
   //也就是这块 可以看出 如果断路器当前是开启状态或者当前服务实例的请求连接数大于配置的连接数阈值则进行过滤(默认是2147483647,可以通过clientConfig进行配置 Spring Cloud中也就是<clientName>.<nameSpace>.ActiveConnectionsLimit进行配置)
    private boolean shouldSkipServer(ServerStats stats) {//满足其一条件则会返回true
        return CIRCUIT_BREAKER_FILTERING.get() && stats.isCircuitBreakerTripped() || stats.getActiveRequestsCount() >= ((Integer)this.activeConnectionsLimit.get()).intValue();
    }

    public Server choose(Object key) {
        int count = 0;

        for(Server server = this.roundRobinRule.choose(key); count++ <= 10; server = this.roundRobinRule.choose(key)) {
            if (this.predicate.apply(new PredicateKey(server))) {
                return server;
            }
        }

        return super.choose(key);
    }

筛选的条件可以发现是先使用轮询的方式挑选出一个服务实例,然后再进行过滤查看是否满足可以的条件,不满足再轮询下一条。

8.ZoneAvoidanceRule实现PredicateBasedRule类,此处的过滤条件通过构造函数可以看出,字面意思,第一个是根据区域进行筛选,第二个是根据可用性进行筛选

   public void initWithNiwsConfig(IClientConfig clientConfig) {
        ZoneAvoidancePredicate zonePredicate = new ZoneAvoidancePredicate(this, clientConfig);
        AvailabilityPredicate availabilityPredicate = new AvailabilityPredicate(this, clientConfig);
        this.compositePredicate = this.createCompositePredicate(zonePredicate, availabilityPredicate);
    }

ZoneAvoidancePredicate的过滤条件如下:

public boolean apply(@Nullable PredicateKey input) {
        if (!ENABLED.get()) {//查看niws.loadbalancer.zoneAvoidanceRule.enabled配置的熟悉是否为true(默认为true)如果为false没有开启分片过滤 则不进行过滤
            return true;
        } else {
            String serverZone = input.getServer().getZone();//获取配置的分片字符串 默认为UNKNOWN
            if (serverZone == null) {
                return true;
            } else {
                LoadBalancerStats lbStats = this.getLBStats();
                if (lbStats == null) {//无负载均衡的要求
                    return true;
                } else if (lbStats.getAvailableZones().size() <= 1) {
                    return true;//可用的分片(处于Up状态)<=1 当然就没必要再过滤了
                } else {
                    Map<String, ZoneSnapshot> zoneSnapshot = ZoneAvoidanceRule.createSnapshot(lbStats);//key为服务实例配置的Zone
                    if (!zoneSnapshot.keySet().contains(serverZone)) {
                        return true;//如果所有分片的配置都不符合规则 那就没必要继续筛选了 不进行过滤 也就表示当前的分片设置没啥意义了
                    } else {
                        logger.debug("Zone snapshots: {}", zoneSnapshot);
                        Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, this.triggeringLoad.get(), this.triggeringBlackoutPercentage.get());//此处开始挑选可用的区域
                        logger.debug("Available zones: {}", availableZones);
                        return availableZones != null ? availableZones.contains(input.getServer().getZone()) : false;
                    }
                }
            }
        }
    }

对两个过滤条件进行实例化后会通过this.compositePredicate = this.createCompositePredicate(zonePredicate, availabilityPredicate);将过滤条件合并。

 private List<AbstractServerPredicate> fallbacks = Lists.newArrayList();//也就是所有过滤条件都存到这个fallback里了
 public static CompositePredicate.Builder withPredicate(AbstractServerPredicate primaryPredicate) {
        return new CompositePredicate.Builder(primaryPredicate);
    }
    public CompositePredicate.Builder addFallbackPredicate(AbstractServerPredicate fallback) {
            this.toBuild.fallbacks.add(fallback);
            return this;
        }

ZoneAvoidanceRule实现PredicateBasedRule类所以还是会通过父类的choose方法进行选择。

  public Server choose(Object key) {
        ILoadBalancer lb = this.getLoadBalancer();
        Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
        return server.isPresent() ? (Server)server.get() : null;
    }

    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.nextIndex.getAndIncrement() % eligible.size()));
    }

getEligibleServers方法在AbstractServerPredicate的子类CompositePredicate中进行了重写。

public class CompositePredicate extends AbstractServerPredicate {
    private List<AbstractServerPredicate> fallbacks = Lists.newArrayList();
    private int minimalFilteredServers = 1;
    private float minimalFilteredPercentage = 0.0F;
   public List<Server> getEligibleServers(List<Server> servers, Object loadBalancerKey) {
        List<Server> result = super.getEligibleServers(servers, loadBalancerKey);

        AbstractServerPredicate predicate;
        for(Iterator i = this.fallbacks.iterator(); (result.size() < this.minimalFilteredServers || result.size() <= (int)((float)servers.size() * this.minimalFilteredPercentage)) && i.hasNext(); result = predicate.getEligibleServers(servers, loadBalancerKey)) {
            predicate = (AbstractServerPredicate)i.next();
        }

        return result;
    }
}

先使用父类的getEligibleServers进行过滤一遍( 默认情况下也就是没过滤)

然后按照fallbacks中存储的过滤器顺序进行过滤(此处就行先ZoneAvoidancePredicate然后AvailabilityPredicate)

当然进行下一条过滤是存在条件的 也就是:

(result.size() < this.minimalFilteredServers || result.size() <= (int)((float)servers.size() * this.minimalFilteredPercentage)) && i.hasNext() 

当前过滤后的实例结果集大小小于最小过滤集合总数了(此处小于默认值1也就是0了)或者过滤后的结果集大小小于实例总数的最小过滤集合百分比了(此处比例因子是0所有相当于结果集大小还是0了)也就是当前服务示例的结果集以及不满足继续过滤的需求了 但这时候&& i.hasNext() 也就是过滤条件还没结束。。则继续进行过滤。

反复琢磨了会。。没看懂啊!!什么情况,假如父类过滤后result.size()>0的话,那循环条件中直接就(xx;false&&true;xxxx)了直接就退出了,那过滤条件是摆设么。。。换句话说,result.size()=0了 满足(xx;true&&true;xxxx)然后开始执行xxxx的过滤条件了。。问题上result都为空了。还过滤什么?!

总结:

Spring Cloud使用Feign+Ribbon可以方便的实现客户端负载均衡策略,而且提供多种负载规则,当然也可以通过实现AbstractLoadBalancerRule抽象类或者IRule进行扩展。简单方便。

时间: 2024-10-09 10:58:54

Netflix中的负载均衡策略的相关文章

分布式环境中的负载均衡策略

在分布式系统中相同的服务常常会部署很多台,每一台被称为一个服务节点(实例).通过一些负载均衡策略将服务请求均匀地分布到各个节点,以实现整个系统支撑海量请求的需求.本文描述一些简单的负载均衡策略. Round-robin 简单地轮询.记录一个选择位置,每次请求来时调整该位置到下一个节点: curId = ++curId % nodeCnt 随机选择 随机地在所有节点中选择: id = random(nodeCnt); 本机优先 访问后台服务的访问者可能本身是一个整合服务,或者是一个proxy,如果

撸一撸Spring Cloud Ribbon的原理-负载均衡策略

在前两篇<撸一撸Spring Cloud Ribbon的原理>,<撸一撸Spring Cloud Ribbon的原理-负载均衡器>中,整理了Ribbon如何通过负载均衡拦截器植入RestTemplate,以及调用负载均衡器获取服务列表,如何过滤,如何更新等的处理过程. 因为,负载均衡器最终是调用负载均衡策略的choose方法来选择一个服务,所以这一篇,整理Ribbon的负载均衡策略. 策略类 RandomRule RoundRobinRule RetryRule WeightedR

springcloud的两种负载均衡策略

前言: 之前写了通过Ribbon+RestTemplate实现调用服务,此处我再系统的说一下两者的区别 一.springcloud的负载均衡策略 1.Ribbon 是基于Netflix Ribbon实现的一套客户端 负载均衡的工具,类似Nginx主要功能时提供客户端的软件负载均衡算法LB就是负载均衡,集中式(F5),进程内(Nginx),消费者可以自动看从Eureka中拿到对应的服务列表,默认进行轮询RoundRobinRule 下图是RestTemplate的自带的7中均衡策略 我们在之前通过

Netflix Ribbon(负载均衡)介绍

一.Ribbon是什么? Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具. Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起.我们在配置文件中列出负载均衡所有的机器,Ribbon会自动的帮助我们基于某种规则(如简单轮询.随机连接等等)去连接这些机器.Ribbon客户端组件提供了一列完善的配置项(如连接超时.重试等等),我们也能很容易的使用Ribbon实现自定义的负载均衡

负载均衡策略

在实际应用中,我们可能不想仅仅是把客户端的服务请求平均地分配给内部服务器,而不管服务器是否宕机.而是想使Pentium III服务器比Pentium II能接受更多的服务请求,一台处理服务请求较少的服务器能分配到更多的服务请求,出现故障的服务器将不再接受服务请求直至故障恢复等等. 选择合适的负载均衡策略,使多个设备能很好的共同完成任务,消除或避免现有网络负载分布不均.数据流量拥挤反应时间长的瓶颈.在各负载均衡方式中,针对不同的应用需求,在OSI参考模型的第二.三.四.七层的负载均衡都有相应的负载

Ribbon负载均衡策略配置

在这里吐槽一句:网上很多文章真是神坑,你不看还好,看了只会问题越来越多,就连之前的问题都没有解决!!! 不多说了,Ribbon作为后端负载均衡器,比Nginx更注重的是请求分发而不是承担并发,可以直接感知后台动态变化来指定分发策略.它一共提供了7种负载均衡策略: 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 选择一个最小的并

分布式进阶(十九) 基于集群的动态反馈负载均衡策略

基于集群的动态反馈负载均衡策略 基于动态反馈机制的集群负载均衡算法研究 目前应用最为广泛的集群计算技术主要分为三大类:高可用性集群技术.高性能计算集群技术和负载均衡集群技术. 德国的CarlAdamPetri于1962年在他的博士论文<自动机通信>中提出了Petri网的概念,它是一种适合于描述异步.并发.分布式系统的图形数学工具. 动态WRR调度算法 这是一个目前普遍使用的调度算法,算法在WRR的基础上加入了根据服务器端的负载信息周期性地调整服务器性能权值的过程.其基本思想是:根据CPU利用率

Dubbo负载均衡策略

在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用. 可以自行扩展负载均衡策略,参见:负载均衡扩展Random LoadBalance 随机,按权重设置随机概率. 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重. 权重加倍 RoundRobin LoadBalance 轮循,按公约后的权重设置轮循比率. 存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在

数据库读写分离和负载均衡策略

最近在学习数据库的读写分离和主从复制,采用的是一主多从策略,采用轮询的方式,读取从数据库的内容.但是,假如某一台从数据库宕机了,而客户端不知道,每次轮选到此从数据库,不都要报错?到网上查阅了资料,找到一篇不错的博文,不仅讲了解决方案,也详细的讲述了数据库的分区,分表,集群和负载均衡策略,博文原址http://www.cnblogs.com/zhongxinWang/p/4262650.html 第1章 引言 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的互