LoadBalancer 算法配置

前面章节介绍了 Spring Cloud 自带的 LoadBalancer 负载均衡器简单用法,默认使用轮询算法。本章节将介绍怎样通过配置文件指定其他负载均衡算法(随机算法)。

提供 User 服务

参考“Netflix Ribbon 简单实例”章节提供的 User 服务,这里将不再赘述。需要注意的是,这里的 User 服务需要注册到 Eureka 注册中心,因此需要在 application.yml 配置文件中添加如下配置:

# 端口不需要指定,通过命令行动态指定
spring:
  application:
    name: user

# 服务地址
eureka:
  instance:
    hostname: localhost
    # 心跳间隔5s,默认30s。每一个服务配置后,心跳间隔和心跳超时时间会被保存在server端,
    # 不同服务的心跳频率可能不同,server 端会根据保存的配置来分别探活
    lease-renewal-interval-in-seconds: 5
    # 心跳超时时间10s,默认90s。从client端最后一次发出心跳后,达到这个时间没有再次发出
    # 心跳,表示服务不可用,将它的实例从注册中心移除
    lease-expiration-duration-in-seconds: 10
  client:
    service-url:
      # 注册中心路径,表示我们向这个注册中心注册服务,如果向多个注册中心注册,用“,”进行分隔
      defaultZone: http://localhost:8077/eureka

实现客户端

添加 maven 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!-- 省略代码 -->
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2020.0.1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    <!-- 省略代码 -->
</project>

上面添加了 Spring Cloud 和 Spring Boot 依赖,以及 Eureka client 依赖。

application.yml 配置

在该配置文件中指定 Eureka 注册中心地址,以及应用名称和端口。配置如下:

server:
  port: 8080

spring:
  application:
    name: demo

eureka:
  client:
    serviceUrl:
      # 指定注册中心
      defaultZone: http://localhost:8077/eureka/

配置 RestTemplate 类

创建 RestTemplateConfig 类,用来配置 RestTemplate 类,并且在该类上面添加 @LoadBalanced 注解,该注解用来在 RestTemplate 类上面启用负载均衡功能。

同时,该配置类在类上面添加 @LoadBalancerClient 注解,用来指定 USER 服务的负载均衡配置,这里我们的配置类 ReactorLoadBalancerConfig  中指定 LoadBalancer 负载均衡算法为随机算法。代码如下:

import com.hxstrive.springcloud.ReactorLoadBalancerConfig;
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 的负载均衡算法
@LoadBalancerClient(value = "USER", configuration = ReactorLoadBalancerConfig.class)
public class RestTemplateConfig {

    // 配置一个 RestTemplate
    @Bean
    // 添加该注解后,可以使得 RestTemplate 拥有负载均衡能力
    @LoadBalanced
    public RestTemplate restTemplate() {
        System.out.println("init RestTemplate");
        return new RestTemplate();
    }

}

负载均衡配置

创建 ReactorLoadBalancerConfig 配置类,该类中使用 @Bean 创建随机负载均衡算法实现类 RandomLoadBalancer 的实例。代码如下:

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;

public class ReactorLoadBalancerConfig {

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

}

注意:ReactorLoadBalancerConfig 类上面不要添加 @Configuration 注解,并且不能将 ReactorLoadBalancerConfig 配置类放到应用程序能扫描的路径下面。在 Spring Boot 中,默认将扫描 @SpringBootApplication 注解标识的 Application 启动类当前目录及子目录下面的类。

客户端

创建 Demo1 类,使用 @Autowired 注解注入 RestTemplate 实例,然后使用 RestTemplate 实例调用目标用户服务。代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class Demo1 {

    @Autowired
    private RestTemplate restTemplate;

    public void demo() {
        System.out.println("restTemplate = " + restTemplate);
        // 如果你要实现负载均衡,调用地址不能写具体主机地址
        // 需要将主机地址替换成对于服务的服务名,即 spring.application.name 指定的值
        // 你也可以到 Eureka server 中去查看
        String url = "http://USER/info";
        for(int i = 0; i < 21; i++) {
            ResponseEntity<String> resp = restTemplate.getForEntity(url, String.class);
            if(resp.getStatusCode().is2xxSuccessful()) {
                System.out.println(resp.getStatusCode().value() + " :: " + resp.getBody());
            } else {
                System.out.println(resp.getStatusCode().value() + " :: " + resp.getBody());
            }
        }
    }

}

执行结果如下:

200 :: From user2 - Wed Apr 14 23:07:31 CST 2021
200 :: From user2 - Wed Apr 14 23:07:31 CST 2021
200 :: From user3 - Wed Apr 14 23:07:32 CST 2021
...
200 :: From user1 - Wed Apr 14 23:07:36 CST 2021
200 :: From user1 - Wed Apr 14 23:07:36 CST 2021
200 :: From user1 - Wed Apr 14 23:07:36 CST 2021
200 :: From user3 - Wed Apr 14 23:07:37 CST 2021
200 :: From user2 - Wed Apr 14 23:07:38 CST 2021
200 :: From user3 - Wed Apr 14 23:07:38 CST 2021
200 :: From user1 - Wed Apr 14 23:07:39 CST 2021

根据上面的结果得知,我们配置的负载均衡随机算法生效了。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号