SpringBoot实战(二十四)集成 LoadBalancer

2023-10-31

一、简介

1.定义

Spring Cloud LoadBalancerSpring Cloud 框架提供的负载均衡组件,用于在微服务框架中实现服务之间的负载均衡。

2.取代 Ribbon

Spring Cloud LoadBalancer 的设计目标是简化和统一负载均衡的使用方式,并提供良好的扩展性。从 Spring Cloud 2020.0 版本、Spring Boot 2.4.x 版本开始,Spring Boot 框架官方放弃了对 Ribbon 的支持,转而使用 Spring Cloud LoadBalancer 作为默认的负载均衡器。虽然提供了与 Ribbon 类似的功能,但是与 Ribbon 相比,Spring Cloud LoadBalancer 具有更轻量级的实现,更好的性能表现,并且更适合与 Spring Cloud Gateway 等其他组件集成使用

3.主要特点与功能

Spring Cloud LoadBalancer 的主要特点和功能包括:

1)简化集成:Spring Cloud LoadBalancer 可以与 Spring Cloud 服务注册与发现组件(如 Eureka、Consul)集成,从注册中心获取服务信息,并进行负载均衡
2)内置负载均衡策略:Spring Cloud LoadBalancer 提供了一些内置的负载均衡策略,如轮询(Round Robin)随机(Random) 等,可以根据需要选择合适的负载均衡策略。
3)定制负载均衡策略:Spring Cloud LoadBalancer 还支持定制负载均衡策略,开发人员可以根据实际需求自定义负载均衡算法
4)故障转移:当某个服务节点不可用时,Spring Cloud LoadBalancer 可以自动将请求发送到其他可用的节点,提高系统的可靠性和容错性。
5)可扩展性:Spring Cloud LoadBalancer 提供了扩展点,开发人员可以根据需要进行扩展和定制,以满足特定的负载均衡需求。

在使用 Spring Cloud LoadBalancer 时,可以通过相关的依赖和配置来进行集成和使用。它可以与其他 Spring Cloud 组件(如 Spring Cloud Gateway、Spring Cloud OpenFeign 等)一起使用,为应用程序提供完整的微服务环境。

4.LoadBalancer 和 OpenFeign 的关系

很多人一直认为 OpenFeign 和 LoadBalancer 的关系就是简单的包含,其实这种看法是错误的。我们可以看看 Spring Cloud 里产品 Map 图里的关系,就一目了然了。

在这里插入图片描述

OpenFeign 的定位是 annotation 化的 RESTFUL Client。需要认识到 OpenFeign 的本质其实是 Spring Cloud 里面比 RestTemplate 更高阶的一个升级组件,实现的是 RESTFUL Client,只是通过 Open Feign 的一些 annotaion 可以实现的比较简单而已。

在这里插入图片描述

LoadBalancer 是 Spring Cloud 里的一个 Common 组件,是可以给其他组件提供服务的基础组件。使用 LoadBalancer 无需 Open Feign 的集成打开 LoadBalancer 的支持功能,有关 RestTemplate 的地方就可以实现客户端的负载均衡了,OpenFeign 是 RestTemplate 的扩展,当然也就同样可以支持到负载均衡。

细心的朋友可以发现,咱们下面介绍的有关 Loadbalance 的使用,基本上都是和 OpenFeign 没有任何联系的; OpenFeign 只是我们后来进行验证效果的方式。


二、使用场景一:Eureka + LoadBalancer

服务架构图如下:

在这里插入图片描述

服务列表如下:

在这里插入图片描述

服务A:loadbalancer-consumer 消费者

1.Maven依赖

注意:这里的 LoadBalancer 依赖必须引入,否则即使编译不报错,负载均衡也是失效的。

<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

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

<!-- LoadBalancer -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
2.application.yml配置
server:
  port: 8081

spring:
  application:
    name: loadbalancer-consumer

#eureka client
eureka:
  client:
    service-url:
      defaultZone: http://demo:Demo2023@localhost:1001/eureka/
  instance:
    hostname: localhost
    prefer-ip-address: true # 是否使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
    lease-renewal-interval-in-seconds: 5 # 实例续期心跳间隔(默认30s),设置之后启动服务不需要等很久就可以访问到服务的内容
    lease-expiration-duration-in-seconds: 15 # 实例续期持续多久后失效(默认90s)
3.RestTemplateConfig.java
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;

/**
 * <p> @Title RestTemplateConfig
 * <p> @Description RestTemplate配置类
 *
 * @author zhj
 * @date 2023/9/17 20:58
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
4.DemoController.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * <p> @Title DemoController
 * <p> @Description 测试Controller
 *
 * @author ACGkaka
 * @date 2023/4/24 18:02
 */
@Slf4j
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumeTest")
    public Object test() {
        log.info(">>>>>>>>>>【INFO】DemoController.consumeTest()...");
        String url = "http://loadbalancer-producer/demo/produceTest";
        return restTemplate.getForObject(url, Object.class);
    }
}

服务B:loadbalancer-producer 生产者

1.Maven依赖
<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- Eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.application.yml配置
server:
  port: 8082

spring:
  application:
    name: loadbalancer-producer

#eureka client
eureka:
  client:
    service-url:
      defaultZone: http://demo:Demo2023@localhost:1001/eureka/
  instance:
    hostname: localhost
    prefer-ip-address: true # 是否使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
    lease-renewal-interval-in-seconds: 5 # 实例续期心跳间隔(默认30s),设置之后启动服务不需要等很久就可以访问到服务的内容
    lease-expiration-duration-in-seconds: 15 # 实例续期持续多久后失效(默认90s)
3.DemoController.java
import com.demo.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p> @Title DemoController
 * <p> @Description 测试Controller
 *
 * @author ACGkaka
 * @date 2023/4/24 18:02
 */
@Slf4j
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Value("${server.port}")
    private String port;

    @RequestMapping("/produceTest")
    public Result<Object> produceTest() {
        Result<Object> result = Result.succeed();
        log.info(">>>>>>>>>>【INFO】DemoController.produceTest()...");
        return result.setData("Hello, I'm from port: " + port);
    }
}

调用测试

请求地址:http://localhost:8081/demo/consumeTest

可以发现分别打印了不同的服务端口,说明负载生效:

在这里插入图片描述

在这里插入图片描述


三、使用场景二:Eureka + LoadBalancer + OpenFeign

服务架构图如下:

在这里插入图片描述

服务列表如下:

在这里插入图片描述

服务A:loadbalancer-feign-a

1.Maven依赖
<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

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

<!-- OpenFeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.application.yml配置
server:
  port: 8081

spring:
  application:
    name: loadbalancer-feign-a

#eureka client
eureka:
  client:
    service-url:
      defaultZone: http://demo:Demo2023@localhost:1001/eureka/
  instance:
    hostname: localhost
    prefer-ip-address: true # 是否使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
    lease-renewal-interval-in-seconds: 5 # 实例续期心跳间隔(默认30s),设置之后启动服务不需要等很久就可以访问到服务的内容
    lease-expiration-duration-in-seconds: 15 # 实例续期持续多久后失效(默认90s)

##feign参数优化
feign:
  client:
    config:
      # 这里用 default 就是全局配置,如果是写服务名称,则是针对某个服务的配置。
      default:
        # 日志级别(忽略大小写),包括:NONE(默认)、BASIC、HEADERS、FULL
        loggerLevel: FULL
3.DemoController.java
import com.demo.common.Result;
import com.demo.feign.DemoFeignClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Value("${server.port:}")
    private String port;

    @Autowired
    private DemoFeignClient demoFeignClient;

    @GetMapping("/feignTest")
    public Result<Object> feignTest() {
        return demoFeignClient.test();
    }
}
4.DemoFeignClient.java
import com.demo.common.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(value = "loadbalancer-feign-b")
public interface DemoFeignClient {

    @GetMapping("/demo/test")
    Result<Object> test();
}

服务B:loadbalancer-feign-b

1.Maven依赖
<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- Eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.application.yml配置
server:
  port: 8082

spring:
  application:
    name: loadbalancer-feign-b

#eureka client
eureka:
  client:
    service-url:
      defaultZone: http://demo:Demo2023@localhost:1001/eureka/
  instance:
    hostname: localhost
    prefer-ip-address: true # 是否使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
    lease-renewal-interval-in-seconds: 5 # 实例续期心跳间隔(默认30s),设置之后启动服务不需要等很久就可以访问到服务的内容
    lease-expiration-duration-in-seconds: 15 # 实例续期持续多久后失效(默认90s)
3.DemoController.java
import com.demo.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/demo")
public class DemoController {

    @Value("${server.port:}")
    private String port;

    @GetMapping("/test")
    public Result<Object> test() {
        String data = "This is a test! port:" + port;
        log.info(">>>>>>>>>> 【INFO】data:{}", data);
        return Result.succeed().setData(data);
    }
}

调用测试

请求地址:http://localhost:8081/demo/feignTest

可以发现分别打印了不同的服务端口,说明负载生效:

在这里插入图片描述

在这里插入图片描述

整理完毕,完结撒花~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot实战(二十四)集成 LoadBalancer 的相关文章

随机推荐

  • vs2019登录不上账号怎么办

    别用校园网 用手机热点几分钟就登录上了 惨痛的教训
  • Android APP间跳转

    1 通过包名启动APP 启动方式 只需知道目标APP包名即可 例如 app1 跳转到app2 app2包名为 com demo skipdemo app1启动代码如下 通过目标APP的包名创建intent对象 Intent intent g
  • Hyper-V安装图形化界面

    七 Hyper V安装图形化界面 此处主要需要时间下载界面的安装包 故在此只贴出操作 1 登录 然后键入命令 yum grouplist 可以看到Avilable Environment Groups 中有图形界面GNOME Desktop
  • 求特殊方程的正整数解

    本题要求对任意给定的正整数N 求方程X2 Y2 N的全部正整数解 输入格式 输入在一行中给出正整数N 10000 输出格式 输出方程X2 Y2 N的全部正整数解 其中X Y 每组解占1行 两数字间以1空格分隔 按X的递增顺序输出 如果没有解
  • SpringBoot不同环境加载不同配置文件

    Spring不同环境加载不同配置文件 resource profile 我们在使用spring的时候 一般都会有不同的环境需要部署 开发环境 测试环境和生产环境 而不同的环境则会有不同的配置 比如数据库ip 解决这个问题 我所熟悉的有两种策
  • java中如何将String类型的日期格式为yyyyMMdd转化为date类型的yyyy-MM-dd格式

    今天在做webservice接口服务的时候 xml文件传入的一个节点为人员的出生日期 对应实体类的字段类型为Date类型 获取到的值为String类型 代码如下 获取的值为 19570323 String dateString emp ge
  • jquery之index与selectedIndex

    晚上有时间 继续再写一点 我们来讲一下关于select表单的所有操作 在项目中还是有很多地方需要用到的 讲select之前先讲一下index 的用法 很长时间之前用过一回 熟悉一下还是有用处的 1 index 同级元素的index 获得第一
  • JavaParser入门:以编程方式分析Java代码

    我最喜欢的事情之一是解析代码并对其执行自动操作 因此 我开始为JavaParser做出贡献 并创建了两个相关项目 java symbol solver和Effectivejava 作为JavaParser的贡献者 我反复阅读了一些非常类似的
  • cv2读取视频每10帧保存一张图像

    读取本地mp4视频 每隔10帧保存一张图像到本地 导入所有必要的库 import cv2 import os RootDir Users billiards SaveDir os path join RootDir data 从指定的路径读
  • GICP 配准点云(附python 代码)

    import open3d as o3d import numpy as np import copy def draw registration result src tar transformation source temp copy
  • IP地址分类(A,B,C,D,E类)

    A类的10 0 0 0 10 255 255 255 B类的172 16 0 0 172 31 255 255 C类的192 168 0 0 192 168 255 255为私网IP 除此之外 A B C三类的所有其余IP都是公网IP 或者
  • 记录Python学习 1:列表字符串转数字

    问题 如何将列表 1 2 3 4 5 中的字符串型转化为数值型 通常在使用 lst input split 获得输入时 列表里为字符串型 有时需要进行转换 常用的有两种方法 方法一 利用列表推导式 lst 1 2 3 4 5 lst int
  • android APP调用系统方法

    一般来说 有些系统方法是不提供在 中的 这种情况下 需要把app的源码放到系统源码的目录下编写Android mk进行编译 使其能访问到 hide的系统方法 但是 即使编译通过 在系统中运行的时候 仍然会碰到权限被拒绝的问题 昨天 我在AP
  • 语句覆盖、条件覆盖、判定覆盖、条件-判定覆盖、组合覆盖、路径覆盖

    文章目录 语句覆盖 判定覆盖 条件覆盖 条件 判定覆盖 组合覆盖 路径覆盖 逻辑覆盖率 语句覆盖 lt 条件覆盖 lt 判定覆盖 lt 条件 判定覆盖 lt 组合覆盖 lt 路径覆盖 语句覆盖 基本思想 设计用例 使程序中的每个可执行语句至
  • DENOISING DIFFUSION IMPLICIT MODELS 论文笔记

    前言 生成模型现在主要分为两类 分别是GAN和Diffusion Model 但是GAN存在一个很棘手的问题就是训练不稳定 这也是Diffusion Model相比之下的优势 DDPM是基于Markovian扩散过程的模型 虽然在生成模型上
  • Java循环结构和DeBug概述

    循环结构 掌握while 循环 先判断在执行 1 循环初始化变量 2 循环条件 3 循环操作 4 循环出口 将循环条件逐渐变为不满足 例图下 do while 循环 先执行在判断 1 声明键盘录入 无论条件是否合格 都会先执行依次循环操作
  • Basic Level 1067 试密码 (20分)

    题目 当你试图登录某个系统却忘了密码时 系统一般只会允许你尝试有限多次 当超出允许次数时 账号就会被锁死 本题就请你实现这个小功能 输入格式 输入在第一行给出一个密码 长度不超过 20 的 不包含空格 Tab 回车的非空字符串 和一个正整数
  • MQTT 消息通信工具使用

    MQTT 介绍 MQTT是机器对机器 M2M 物联网 IoT 连接协议 它被设计为一个极其轻量级的发布 订阅消息传输协议 对于需要较小代码占用空间和 或网络带宽非常宝贵的远程连接非常有用 是专为受限设备和低带宽 高延迟或不可靠的网络而设计
  • Node.js的前世今生,Node.js和npm安装教程

    Node js是目前非常火热的技术 但是它的诞生经历却很奇特 众所周知 在Netscape设计出JavaScript后的短短几个月 JavaScript事实上已经是前端开发的唯一标准 后来 微软通过IE击败了Netscape后一统桌面 结果
  • SpringBoot实战(二十四)集成 LoadBalancer

    目录 一 简介 1 定义 2 取代 Ribbon 3 主要特点与功能 4 LoadBalancer 和 OpenFeign 的关系 二 使用场景一 Eureka LoadBalancer 服务A loadbalancer consumer