ribbon简单使用及自带的负载均衡算法

这里举个例子,比如系统的时候,用户访问量巨大,一台机器肯定是不可能的,为了实现高可用,肯定会实现集群,这里只以用户服务为例。大致图如下:
SpringCloud之服务负载均衡ribbon(二) - 图1jiegoutu.png
这里只是简单的画了一下图,当提供者集群后,我们就会遇到这样一个问题,到底访问哪个呢,系统肯定不会知道,当我们集成了ribbon后(我目前用的eureka版本已经默认集成了ribbon,旧的版本貌似还需要添加ribbon的相关依赖),ribbon会提供一种默认的负载均衡算法实现自主选择其中一个服务进行调用,默认是轮询算法,就是这次我调用1号服务,下次2号,依次轮询。
测试:
SpringCloud之服务负载均衡ribbon(二) - 图2morenlunxun1.png SpringCloud之服务负载均衡ribbon(二) - 图3morenlunxun2.png morenlunxun3.pngg
可以看出每个服务都执行了相同的次数,说明默认采用的轮询算法,默认支持的负载均衡算法还有以下:
ribbon_suanfa.png
那我们就要问了,我们更改默认的轮询算法呢,其实很简单,我们只要指定一个bean覆盖掉默认的即可,比如我们想要使用RandomRule随机算法,我们只需要定义一个bean,返回我们的randomRule即可。

  1. 1 @Bean
  2. 2 public IRule myRule() {
  3. 3 return new RandomRule();
  4. 4 }
  5. 复制代码

测试就不截图了,可以自己试试。

自定义负载均衡算法

尽管ribbon已经自带了上面的负载均衡算法,但是默认的有时候可能不能满足我们的某些需求,ribbon默认还支持自定义负载均衡算法,比如我们现在有一个需求,每个服务需要轮询3次,即1号服务3次,2号3次,依次类推。这时我们就需要一个注解@RibbonClient,并设置参数。具体如图:

1package com.lytw13.demo;
 2
 3import com.lytw13.rule.MyRule;
 4import com.netflix.loadbalancer.IRule;
 5import org.springframework.boot.SpringApplication;
 6import org.springframework.boot.autoconfigure.SpringBootApplication;
 7import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 8import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 9import org.springframework.cloud.netflix.ribbon.RibbonClient;
10import org.springframework.context.annotation.Bean;
11import org.springframework.web.client.RestTemplate;
12
13@EnableEurekaClient
14@SpringBootApplication
15@RibbonClient(value = "USER",configuration = MyRule.class)
16public class WebApplication {
17    public static void main(String[] args) {
18        SpringApplication.run(WebApplication.class,args);
19    }
20    @Bean
21    @LoadBalanced
22    RestTemplate restTemplate() {
23        return new RestTemplate();
24    }
25
26    @Bean
27    public IRule myRule() {
28        return new MyRule();
29    }
30}
复制代码

然后我们需要定义自己的算法,我们只要实现IRule接口或者集成AbstractLoadBalancerRule这个类,重写里面的算法即可。注意:我们自定义的算法不能在@ComponetScan能扫描的包下,这样会失败。

1package com.lytw13.rule;
 2
 3import com.netflix.client.config.IClientConfig;
 4import com.netflix.loadbalancer.*;
 5import org.slf4j.Logger;
 6import org.slf4j.LoggerFactory;
 7
 8import java.util.List;
 9import java.util.concurrent.atomic.AtomicInteger;
10
11public class MyRule extends AbstractLoadBalancerRule {
12    private AtomicInteger nextServerCyclicCounter;
13    private static final boolean AVAILABLE_ONLY_SERVERS = true;
14    private static final boolean ALL_SERVERS = false;
15    private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);
16    private int total = 0;
17    private int current = 0;
18    public MyRule() {
19        nextServerCyclicCounter = new AtomicInteger(0);
20    }
21    public MyRule(ILoadBalancer lb) {
22        this();
23        setLoadBalancer(lb);
24    }
25    public Server choose(ILoadBalancer lb, Object key) {
26        if (lb == null) {
27            log.warn("no load balancer");
28            return null;
29        }
30        Server server = null;
31        int count = 0;
32
33        while (server == null && count++ < 10) {
34            List<Server> reachableServers = lb.getReachableServers();
35            List<Server> allServers = lb.getAllServers();
36            int upCount = reachableServers.size();
37            int serverCount = allServers.size();
38
39            if ((upCount == 0) || (serverCount == 0)) {
40                log.warn("No up servers available from load balancer: " + lb);
41                return null;
42            }
43            if (total<3) {
44                server = reachableServers.get(current);
45                total++;
46            }else {
47                total = 0;
48                current++;
49                if (current >= reachableServers.size()) {
50                    current = 0;
51                }
52            }
53            if (server == null) {
54                /* Transient. */
55                Thread.yield();
56                continue;
57            }
58            if (server.isAlive() && (server.isReadyToServe())) {
59                return (server);
60            }
61
62            // Next.
63            server = null;
64        }
65        if (count >= 10) {
66            log.warn("No available alive servers after 10 tries from load balancer: "
67                    + lb);
68        }
69        return server;
70    }
71    @Override
72    public Server choose(Object key) {
73        return choose(getLoadBalancer(), key);
74    }
75    @Override
76    public void initWithNiwsConfig(IClientConfig clientConfig) {
77    }
78}
复制代码

测试:
SpringCloud之服务负载均衡ribbon(二) - 图4zidingyisuanfa1.png
SpringCloud之服务负载均衡ribbon(二) - 图5zidingyisuanfa2.png
SpringCloud之服务负载均衡ribbon(二) - 图6zidingyisuanfa3.png
作者:lytw1315
链接:https://juejin.im/post/5df642e2f265da339f7cf39d
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。