文章目录

  • Spring Cloud 学习 | - 04 - 自定义Ribbon负载均衡策略
  • 1. 启动Eureka
  • 1.1 Eureka依赖:
  • 1.2 配置文件
  • 1.3 开启EurekaServer功能
  • 2. 启动服务提供者
  • 2.1 主要依赖
  • 2.2 配置文件
  • 2.3 启用服务发现注解
  • 2.4 Service
  • 2.5 Controller
  • 2.6 启动服务
  • 3. 自定义负载均衡策略
  • 3.1 新建一个测试类和方法
  • 3.2 修改负载均衡规则
  • 3.3 自定义负载均衡策略
  • 3.3.1 方式一配置文件.yml实现
  • 3.3.2 方式二配置类Configuration实现
  • 4. 附:Ribbon内嵌的7种负载均衡的策略说明:


Spring Cloud 学习 | - 04 - 自定义Ribbon负载均衡策略

学习 Spring Cloud 之路,文中 Spring Boot 版本为 2.1.3.RELEASESpring Cloud 版本为 Greenwich.SR1

接上篇 Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡),我们使用Rest+Ribbon实现了负载均衡,默认策略是轮询策略。接下来,我们看看怎么修改负载均衡的规则。

1. 启动Eureka

具体Eureka相关的,这里就不再赘述,详情请参阅之前的文章内容。这里贴一下基本的配置及代码。

1.1 Eureka依赖:

主要Maven依赖:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

1.2 配置文件

application.yml

## app port conf
server:
  port: 8761
spring:
  application:
    name: spring-cloud-eureka
eureka:
  client:
    service-url:
      # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址
      defaultZone: http://localhost:${server.port}/eureka
    register-with-eureka: false #由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
    fetch-registry: false #由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为false
  server:
    enable-self-preservation: false # 关闭自我保护机制

1.3 开启EurekaServer功能

@SpringBootApplication
@EnableEurekaServer
public class SpringCloudEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudEurekaApplication.class, args);
    }
}

启动Eureka服务。

2. 启动服务提供者

具体这里就不详细说明了,请查阅前一篇博文,这里主要贴一下主要配置和代码。

2.1 主要依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.2 配置文件

server:
  port: 8090
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true # 返回ip而不是host名称
#    ip-address: 127.0.0.1 # 指定自己的ip信息
    lease-expiration-duration-in-seconds: 15 # 服务失效时间,默认值90秒
    lease-renewal-interval-in-seconds: 5 # 服务续约(renew)的间隔,默认为30秒
spring:
  application:
    name: user-provider

2.3 启用服务发现注解

@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {

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

2.4 Service

@Service
public class UserServiceImpl implements UserService {
    /**
     * 查询所有用户
     * @return
     */
    @Override
    public List findAll() {
        List list = Arrays.asList("Cindy","Pony","Marry");
        return list;
    }
}

2.5 Controller

@RestController
@RequestMapping("/user")
public class UserController {
    @Value("${server.port}")
    private String port;
    @Autowired
    private UserService userService;

    @GetMapping("/list")
    public Map list(){
        Map<String,Object> data = new HashMap<>(16);
        data.put("port", port);
        data.put("rows", userService.findAll());
        return data;
    }
}

2.6 启动服务

分别启动2个user-provider服务,端口分别为80908091,详细步骤请参阅上一篇博文。

启动完成后,查看eureka注册中心:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_Spring Cloud

3. 自定义负载均衡策略

3.1 新建一个测试类和方法

我们用LoadBalancerClient获取应用实例,在控制台输入主机和端口,重复10次。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserConsumerApplicationTests {

    @Autowired(required = false)
    private LoadBalancerClient client;

    @Test
    public void testRule(){
        for (int i = 0; i < 10; i++) {
            ServiceInstance instance = client.choose("user-provider");
            String host = instance.getHost();
            int port = instance.getPort();
            System.err.println("Host=" + host + ",port=" + port);
        }
    }
}

先来看一下,默认的轮询测试结果:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_自定义_02


结果是顺序轮流的调用。

3.2 修改负载均衡规则

我们只要注入一个实现IRule的Bean即可,这里注入Ribbon里自带的一个规则为例(其他的,请实现IRule接口即可),默认实现的规则有:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_LoadBalance_03


这里以RandomRule为例:

新建一个Configuration配置类,或者直接在启动类XxxApplication里注入IRule的Bean:

@Bean
    public IRule customRule(){
        return new RandomRule();
    }

这样便可以了。我们测试一下:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_自定义_04


输出结果是随机的,证明随机的策略生效了。

下边我们说下,对指定的服务配置负载均衡策略的方法。

3.3 自定义负载均衡策略

3.3.1 方式一配置文件.yml实现

官方的说明文档如下:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_Spring Cloud_05


.yml配置的格式:<clientName>.ribbon.NFLoadBalancerRuleClassName:自定义的Rule规则类(需要实现IRule接口),我们修改自己的.yml配置,新增如下内容:

user-provider: # 我们为user-provider这个服务配置自定义的策略
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 自定义的策略类

注释掉刚才全局的策略配置:

// @Bean
    // public IRule customRule(){
    //     return new RandomRule();
    // }

这样就OK了,我们测试游戏,是不是随机的调用规则:

springcloud nacos 实现负载均衡 springcloud自定义负载均衡_Spring Cloud_06


我们看到是随机的,配置正确。

3.3.2 方式二配置类Configuration实现
  • 先注释掉刚才的.yml配置方式代码:
#user-provider: # 我们为user-provider这个服务配置自定义的策略
#  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 自定义的策略类
  • 我们新建一个Rrule配置类,这个类要注意下package的位置,不能再XxxApplication启动类同级及其子包下,Sprig Cloud官方文档说明如下:
  • springcloud nacos 实现负载均衡 springcloud自定义负载均衡_自定义_07

  • 新建配置类CustomRuleConfig,路径如下
@Configuration
public class CustomRuleConfig {
    @Bean
    public IRule customRule(){
        return new RandomRule();
    }
}
  • 修改启动类XxxApplication,添加注解@RibbonClient
@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "user-provider",configuration = CustomRuleConfig.class)
public class UserConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

name:表示是指定哪个服务启用这个策略,
configuration :表示指定哪个自定义的策略规则

  • 好了,我们测试一下:

    结果是随机的,采用了指定负载均衡的规则。

4. 附:Ribbon内嵌的7种负载均衡的策略说明:

No.

Rule

Desc

1

RoundRobinRule

轮询

2

RandomRule

随机

3

AvailabilityFilteringRule

会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服 务,然后对剩余的服务列表按照轮询策略进行访问

4

WeightedResponseTimeRule

根据平均响应事件计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule 策略,等统计信息足够,会切换到WeightedResponseTimeRule

5

RetryRule

先按照RoundRobinRule 的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务

6

BestAvailableRule

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

7

ZoneAvoidanceRule

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