Ribbon负载均衡策略


文章目录

  • Ribbon负载均衡策略
  • 1.默认-轮询策略
  • 1.1 修改User服务,使用Ribbon默认轮询策略
  • 1.2 RestTemplate配置
  • 1.3 RestTemplate访问Order订单服务
  • 1.4 重启user服务
  • 1.5 测试Ribbon轮询访问
  • 2.随机策略
  • 2.1 定义RandomLoadBalancer 随机负载均衡策略
  • 2.2 LoadBalancerClients指定使用策略
  • 2.3 重启user服务,验证随机策略



Ribbon默认的是轮询策略,那么还有其他策略么?该如何使用其他策略


Ribbon 一共7 种策略

  1. 轮询策略 RoundRobinRule
  2. 随机策略 RandomRule
  3. 轮询重试策略 RetryRule
  4. 响应速度决定权重 WeightedResponseTimeRule
  5. 最优可用 BestAvailableRule, 采用并发连接数判断最优,连接数最小的节点
  6. 可用性过滤规则 AvailabilityFilteringRule
  7. 区域内可用性能最优 ZoneAvoidanceRule

如果需要一些前置配置的比如服务创建及Eureka使用,可以看下上一篇文章
Ribbon负载均衡(一)Ribbon实战 我使用的版本如下

本文使用的版本是 Springboot-2.6.7 ,Spring Cloud -2021.0.2 , Eureka 版本3.1.2

dubbo负载均衡 轮询默认权重_dubbo负载均衡 轮询默认权重

这坑爹玩意,这里面在Eureka 下面的jar包中是没有ribbon的, 没IRule接口,如何定义负载均衡策略 ?推荐使用 Springcloud LoadBalancer 替换RibbonSpringcloud LoadBalancer只有两种负载均衡策略+自定义负载均衡策略

dubbo负载均衡 轮询默认权重_ribbon_02


springcloud 2020.0.1 版本之后 删除了eureka中的ribbon,替代ribbon的是spring cloud自带的LoadBalancer

Spring-cloud-starter-loadbalancer 的jar 这个应该是和Ribbon的功能一样,但是他就提供了RandomLoadBalancer 随机 和RoundRobinLoadBalancer 轮询的方式,默认使用的是轮询的方式

dubbo负载均衡 轮询默认权重_移除Ribbon_03

1.默认-轮询策略

我们改造一下

1.1 修改User服务,使用Ribbon默认轮询策略

增加config/RestTemplateConfig 配置文件, 引入RestTemplate便于访问http接口

1.2 RestTemplate配置

RestTemplateConfig.java

package com.ribbon.user.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

        //如果不加上面的注释 @LoadBalanced 就不会从eureka上获取 order服务地址, 也就不会使用负载均衡,
        // 你访问的 http://order/order order服务的host就会找不到
        @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
1.3 RestTemplate访问Order订单服务
package com.ribbon.user.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
public class UserController {


    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/user")
    public String test() {
        log.info("client 发起UserController");
        return "user";
    }


    @GetMapping("/testribbon")
    public String testRibbon() {

        //restTemplate 请求访问 order订单服务的 order URL ,
        // 参数URL   http://order/order   第一个order 就是服务名字 就是注册在Eureka上的 服务名字 第二个order就是 controller 入口
        // 第二个参数String.class 就是 访问返回值
        String result = restTemplate.getForObject("http://order/order", String.class);
        log.info("user 发起UserController 测试ribbon 调用 :{} ", result);
        return result;
    }

}
1.4 重启user服务

访问 localhost:8088/testribbon
如果报错, 看下你的RestTemplate种的@LoadBalanced 注解是否加上,不加上默认是使用正常的restTemplate 访问IP+PORT ,你的URL是 http://order/order 不会去Eureka上获取order服务的地址及端口的

没有@LoadBalanced 注解 会报如下错误
nested exception is java.net.UnknownHostException: order] with root cause
java.net.UnknownHostException: order

2022-05-15 21:51:03.169 ERROR 6216 --- [nio-8088-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://order/order": order; nested exception is java.net.UnknownHostException: order] with root cause

java.net.UnknownHostException: order
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) ~[na:1.8.0_181]

服务正常启动

1.5 测试Ribbon轮询访问

访问testribbon接口,看看RestTemplate访问的是否是轮询访问三个节点中的一个

可以看到顺序那都是 two,one,three,的确是轮询访问三个服务

dubbo负载均衡 轮询默认权重_找不到IRule接口_04

2.随机策略

如何实现Ribbon对order服务随机策略?我们只要定制规则即可? 但是我们已经没了Ribbon 所以你是引入不了 IRule 接口去重新定义Rule负载均衡策略的,咋办?????

SpringCloud重新定义了一套 ReactorLoadBalancer 策略

dubbo负载均衡 轮询默认权重_移除Ribbon_05

2.1 定义RandomLoadBalancer 随机负载均衡策略

定义随机策略

package com.ribbon.user.config;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;


/**
 * 这里不需要 @configuration注解  不需要 不需要!!!!
 * 它可以在RestTemplateConfig中指定 Configuration CustomLoadBalancerConfiguration
 */
public class CustomLoadBalancerConfiguration {

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

为什么这个类上不加 @Configuration 让Spring 扫描到它? 因为官方文档中给除了明确说法 不要加注释@Configuration 或者你可以在Spring 包扫描外 新建这个配置

dubbo负载均衡 轮询默认权重_找不到IRule接口_06

2.2 LoadBalancerClients指定使用策略

修改RestTemplateConfig 配置文件 ,很重要!!!!!
配置LoadBalancerClients 指定你的 service服务 及使用的负载均衡策略

package com.ribbon.user.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration

//在这里配置我们自定义的LoadBalancer策略
// 如果扩展算法 需要自己去实现ReactorServiceInstanceLoadBalancer接口
// 标准@LoadBalancerClients(defaultConfiguration = {name = "CLOUD-PAYMENT-SERVICE", configuration = CustomLoadBalancerConfiguration.class})
//注意这里的name属性 需要和eureka页面中的服务提供者名字保持一致
@LoadBalancerClient(name = "order", configuration = CustomLoadBalancerConfiguration.class)
public class RestTemplateConfig {

    //如果不加上面的注释 @LoadBalanced 就不会从eureka上获取 order服务地址, 也就不会使用负载均衡,
    // 你访问的 http://order/order order服务的host就会找不到
    @Bean
    @LoadBalanced
    //使用这个     @LoadBalanced 注解给restTemplate赋予了负载均衡的能力
    RestTemplate restTemplate() {
        return new RestTemplate();
    }


}
2.3 重启user服务,验证随机策略

访问 http://localhost:8088/testribbon 接口 可以看到 随机取调用某台节点

实现了随机访问的负载均衡模式

dubbo负载均衡 轮询默认权重_dubbo负载均衡 轮询默认权重_07


至此我们已经简单的可以使用 SpringCloud LoadBalancer了 , 这两种都是基本的负载均衡策略,下一篇 我们介绍下 如何用 SpringCloud LoadBalancer 取自定义负载均衡策略