Spring Cloud LoadBalancer 教程

LoadBalancer 简介

Spring Cloud 的 Hoxton.M2 版本整合了新的 LoadBalancer 实现来替代 Ribbon 实现版本。

在 Spring Cloud 中提供了客户端负载均衡器的抽象和实现。对于负载均衡机制,添加了 ReactiveLoadBalancer 接口,并为其提供了基于 Round-Robin(循环)和 Random(随机)的实现。分别为:

  • org.springframework.cloud.loadbalancer.core.RandomLoadBalancer 随机算法负载均衡实现

  • org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer 轮询算法负载均衡实现

下面通过实例来演示 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 类上面启用负载均衡功能。代码如下:

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

@Configuration
public class RestTemplateConfig {

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

}

客户端

创建 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 user1 - Wed Apr 14 22:52:19 CST 2021
200 :: From user3 - Wed Apr 14 22:52:19 CST 2021
200 :: From user2 - Wed Apr 14 22:52:19 CST 2021
...
200 :: From user1 - Wed Apr 14 22:52:26 CST 2021
200 :: From user3 - Wed Apr 14 22:52:26 CST 2021
200 :: From user2 - Wed Apr 14 22:52:26 CST 2021
200 :: From user1 - Wed Apr 14 22:52:27 CST 2021
200 :: From user3 - Wed Apr 14 22:52:27 CST 2021
200 :: From user2 - Wed Apr 14 22:52:28 CST 2021

根据上面调用结果可知,LoadBalancer 默认采用的是轮询算法,下一章节将介绍怎样去自定义配置随机算法。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号