Spring Cloud (七) - Ribbon及底层实现

Ribbon:

概述:

是一个客户端的负载均衡工具,解决消费者如何均匀的选择提供者,

Ribbon 负载均衡策略:

  • RoundRobinRule: 轮询策略,Ribbon以轮询的方式选择服务器,这个是默认值。所以示例中所启动的两个服务会被循环访问;
  • RandomRule: 随机选择,也就是说Ribbon会随机从服务器列表中选择一个进行访问;
  • BestAvailableRule: 最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的;
  • WeightedResponseTimeRule: 带有加权的轮询策略,对各个服务器响应时间进行加权处理,然后在采用轮询的方式来获取相应的服务器;
  • AvailabilityFilteringRule: 可用过滤策略,先过滤出故障的或并发请求大于阈值一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个;
  • ZoneAvoidanceRule: 区域权衡策略,先使用主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例清单,依次使用过滤条件列表中的过滤条件对主过滤条件的结果进行过滤,判断最小过滤数(默认1)和最小过滤百分比(默认0),最后对满足条件的服务器则使用RoundRobinRule(轮询方式)选择一个服务器实例。

RestTemplate

跨服务调用技术,它和feign的使用基本一致。

使用RestTemplate实现负载均衡,它是调用方的负载均衡
使用RestTemplate有多种方式:这里说明三种

	ctrl + shift + t 可以搜索源码中的文件

1. 通过注入bean的方式

  1. 主函数中使用@LoadBalanced注解
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}
  1. service层创建RestTemplate对象并调用,这里使用的是excute(),
 @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/test")
    public Object test(@RequestParam("id")String id){
        Object obj = restTemplate.getForObject("http:/yss/test?id=" + id,Object.class);
        return  obj;
    }
  1. 在被调用方启动多个服务,保证注册名称一致,多调用几次之后,会发现采用的是ribbon的轮询机制

2. LoadBalancerClient 方式

不需要在主函数中添加RestTemplete,这里使用的是choose()

 @Autowired
    private LoadBalancerClient loadBalancerClient;
    @GetMapping("/test")
    public Object test(@RequestParam("id")String id){
        Object obj = "";
//        Object obj = restTemplate.getForObject("http:/yss/test?id=" + id,Object.class);
        //方式二:
        //选择系统中服务的实例,已经实现了负载均衡,然后调用即可
        ServiceInstance instance = loadBalancerClient.choose("服务名");
        String url = String.format("http://%s:%s/yss/add?id=" + id,instance.getHost(),instance.getPort());
        RestTemplate restTemplate = new RestTemplate();
        obj = restTemplate.getForObject(url,Object.class);
        return  obj;
    }

3. RestTemplateBuilder创建

import org.springframework.boot.web.client.RestTemplateBuilder;

public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}

这种方法和第一种方法一样都是通过execute()方法来初始化一个节点,然后根据节点的ip和port来访问

@LoadBalanced 深入说明:

Spring Cloud (七) - Ribbon及底层实现_第1张图片
说明@LoadBalanced配置了LoadBalancerClient(负载均衡器),在原来的基础上进行了加强进入LoadBalancerClient中,可以看到它有三个方法,其中reconstructURI()方法用来重构URL,还有一个execute()方法,这两个方法是为了定义节点的, LoadBalancerClent只有一个实现类RibbonLoadBalancerClient,继承结构:
Spring Cloud (七) - Ribbon及底层实现_第2张图片
其中我们在第二种方式使用的choose()方法是实现的ServiceInstanceChooser
Spring Cloud (七) - Ribbon及底层实现_第3张图片
进入choose()实现的方法中:这里的serviceId作用是通过服务的id来找到对应的负载均衡
Spring Cloud (七) - Ribbon及底层实现_第4张图片
点击getServer(),可以看到这里传递的参数是"default","default"其实代表的就是默认的负载均衡中的轮询机制
Spring Cloud (七) - Ribbon及底层实现_第5张图片
然后进入到chooseServer方法中
Spring Cloud (七) - Ribbon及底层实现_第6张图片
它使用的是子类BaseLoadBalancer中重写的方法,在这里可以看到”return rule.choose(key);“,我们来看一下rule是什么:
Spring Cloud (七) - Ribbon及底层实现_第7张图片
这里"new RoundRobinRule()"就是定义的轮询策略
我们看一下IRule里面:
Spring Cloud (七) - Ribbon及底层实现_第8张图片
其实IRule是专门定义负载均衡策略的,其中比如说:RandomRule(随机策略),RoundRobinRule(轮询),WeightedResponseTimeRule(权重),这里使用的是默认的RoundRobinRule,在RoundRobinRule类中会调用查询服务列表的方法,若启动了三个服务,在这里就会获取到三个服务的ip和port
Spring Cloud (七) - Ribbon及底层实现_第9张图片
Spring Cloud (七) - Ribbon及底层实现_第10张图片
然后再根据轮询来拿到相应的服务信息返回Server也就是方式二中的instance,若使用的是方式一,那么它会调用上面我们说的RibbonLoadBalancerClient类中的reconstructURI()和execute()方法来初始化一个节点,然后根据节点的ip和port来访问

总结:

  1. 首先从注册中心获取一个服务表
  2. 然后根据策略选择其中的一个节点
  3. 然后返回给restTemplete进行调用

自定义负载均衡

官方文档:
Spring Cloud (七) - Ribbon及底层实现_第11张图片
其中users指的是被调用的服务注册名称,在这里我们只需要配置圈出来的部分就可以,其中"com.netflix.loadbalancer"是不变的,只需要配置后面的类名就可以了,你可以再IRule.java中选择对应的策略类名

策略选择:

  1. 一般情况下不需要修改策略
  2. 若一些服务器配置比较好,那么可以修改成权重策略(WeightedResponseTimeRule)

你可能感兴趣的:(SpringCloud,Ribbon)