Spring Cloud 系列之负载均衡 Ribbon

2020-11-11 17:52:19 浏览数 (1)

1.1 简介

1.1.1 概述

  Ribbon 是 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为。为 Ribbon 配置服务提供者地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为 Ribbon 实现自定义的负载均衡算法。Ribbon 现在已经进入维护状态,但目前仍在大规模使用,Spring Cloud 准备使用 LoadBalancer 作为 Ribbon 的替换方案。

1.1.2 相关依赖

  因为现在的注册中心帮我们引入了 Ribbon 我们不需要再次引入就可以直接使用,当然也可以再引入一次没有影响。

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

1.2 简单使用

1.2.1 搭建项目

☞ eureka 项目

1.2.2 开启负载均衡

  开启负载均衡非常简单,只需要在 RestTemplate 的配置方法上加上 @LoadBalanced 注解即可使用最简单的轮询。

代码语言:javascript复制
/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description 消费者启动类
 */
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

1.2.3 使用负载均衡

代码语言:javascript复制
/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description
 */
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/go")
    public void go() {
        List<ServiceInstance> providerServer = discoveryClient.getInstances("ProviderServer");

        if (0 == providerServer.size()) {
            return;
        }

        ServiceInstance serviceInstance = providerServer.get(0);
        String url = serviceInstance.getUri()   "/provider/get";
        System.out.println(url   " --- ");
        String str = restTemplate.getForObject(url, String.class);
        System.out.println(str);

    }
}

  喔嚯!报错了,明明可以访问到为什么会报找不到实例呢?这是应为咱们使用 DiscoveryClient 直接获取到了服务提供者集群中某一个的地址,然后让 RestTemplate 去进行负载均衡。我们都已经拿到了准确地址再怎么进行负载均衡?所以我们这里不能使用 IP 要使用服务名称。

代码语言:javascript复制
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;


    @GetMapping("/go")
    public void go() {
        String url = "http://ProviderServer/provider/get";

        String str = restTemplate.getForObject(url, String.class);
        System.out.println(str);
    }
}

修改完毕之后就可以看到服务提供者是轮换进行提供服务的

1.3 替换负载均衡策略

1.3.1 自带负载均衡策略

策略名

策略描述

RoundRobinRule

轮询选择 server

RandomRule

随机选择一个 serve

RetryRule

先按轮询策略获取服务,如果获取服务失败则在指定时间内重试,获取可用服务

BestAvailableRule

会先过滤由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

AvailabilityFilteringRule

会优先过滤故障实例,再选择并发较小的实例

WeightedResponseTimeRule

对轮询的扩展,响应速度越快的实例选择比重权越大,越容易被选择

ZoneAvoidanceRule

复合判断 server 所在区域的性能和 server 的可用性选择 server

1.3.2 使用配置类

  官方文档明确警告,这个自定义配置类不能放在 @ComponedtScan 所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的 Ribbon 客户端所共享。即在 Spring Boot 主程序扫描的包外定义配置类或在与 Spring Boot 主程序的同一级目录但在排除扫描。配置类创建完毕后为 Spring Boo 主程序添加 @RibbonClient 注解引入配置类,用 name 属性来指定调用的服务名称,configuration 属性指定自定义配置类

代码语言:javascript复制
@Configuration
public class MyRibbonRule {

    @Bean
    public IRule ribbonRule() {
        return new RandomRule();
    }
}
代码语言:javascript复制
@SpringBootApplication
@EnableDiscoveryClient
// 用 name 来指定调用的服务名称,configuration 指定自定义配置类
@RibbonClient(name = "ProviderServer", configuration = MyRibbonRule.class)
public class ConsumerApplication {

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

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

1.3.3 配置文件

代码语言:javascript复制
# 这种配置的优先级低于配置类
# 想要调用的服务名称,即服务提供者名称
ProviderServer:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

☞ 源码

0 人点赞