一、概述

1.1、Ribbon目前也进入维护模式

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

https://github.com/Netflix/ribbon?tab=readme-ov-file#project-status-on-maintenance

image-20240826184153184

https://cloud.spring.io/spring-cloud-netflix/multi/multi__modules_in_maintenance_mode.html#_modules_in_maintenance_mode

将模块置于维护模式意味着 Spring Cloud 团队将不再向该模块添加新功能。我们将修复阻止程序错误和安全问题,还将考虑和审查来自社区的小型拉取请求。我们打算从 Greenwich 发布版本正式发布开始至少一年内继续支持这些模块。以下 Spring Cloud Netflix 模块和相应的启动器将置于维护模式:

image-20240826185000093

https://spring.io/blog/2019/01/23/spring-cloud-greenwich-release-is-now-available

我们建议使用以下内容来替代这些模块提供的功能。

image-20240826185221197

1.2、spring-cloud-loadbalancer概述

LB负载均衡(Load Balance)是什么

简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用),常见的负载均衡有软件Nginx,LVS,硬件 F5等

spring-cloud-starter-loadbalancer组件是什么

Spring Cloud LoadBalancer是由SpringCloud官方提供的一个开源的、简单易用的客户端负载均衡器,它包含在SpringCloud-commons中用它来替换了以前的Ribbon组件。相比较于Ribbon,SpringCloud LoadBalancer不仅能够支持RestTemplate,还支持WebClient(WeClient是Spring Web Flux中提供的功能,可以实现响应式异步请求)

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html

image-20240826190218348

image-20240826190227041

客户端负载VS服务器端负载区别

loadbalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别

Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的。

loadbalancer本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。

二、实战

2.1、改POM

 <dependencies>
        <!--loadbalancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

image-20240826200458210

2.2、写代码

package com.loadbalancer.consumer.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: 史小创
 * @Time: 2024/8/23 下午7:08
 * @Description:
 */

@RestController
public class LoadbalancerConsumerController {
    public static final String URL = "http://LoadbalancerProvider/provider/";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/{id}")
    public String hello(@PathVariable("id") Integer id) {
        return restTemplate.getForObject(URL + id, String.class);
    }
}

image-20240826200754590

package com.loadbalancer.consumer.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
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.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: 史小创
 * @Time: 2024/8/26 下午7:44
 * @Description:
 */


@Configuration
public class RestTemplateConfig {
    /**
     * 这个注解用于启用客户端负载均衡功能。
     * 注解作用在 RestTemplate 上时,Spring 会为 RestTemplate 配置一个拦截器,
     * 这个拦截器会在你调用服务时自动根据服务名称(例如通过 Consul 注册中心注册的服务名)进行负载均衡。
     * 也就是说,当你在 RestTemplate 中使用服务名称来调用服务时,@LoadBalanced 会确保请求被分发到不同的服务实例上,以实现负载均衡。
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

image-20240826200847056

2.3、测试

http://localhost:8888/consumer/66

ec7c9762-b00e-4d3a-8afe-bfda6c73ee49

2.4、负载均衡的算法

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html#switching-between-the-load-balancing-algorithms

在负载平衡算法之间切换 默认使用的 ReactiveLoadBalancer 实现是 RoundRobinLoadBalancer。要切换到其他实现(针对选定服务或所有服务),可以使用自定义 LoadBalancer 配置机制。例如,可以通过 @LoadBalancerClient 注释传递以下配置以切换到使用 RandomLoadBalancer:

image-20240826201808347

package com.loadbalancer.consumer.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
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.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: 史小创
 * @Time: 2024/8/26 下午7:44
 * @Description:
 */


@Configuration
/**
 * @LoadBalancerClient 注解是 Spring Cloud 提供的,用于自定义特定服务的负载均衡配置。
 * value 属性:value = "LoadbalancerProvider" 指定了要为哪个服务自定义负载均衡配置,这里的 "LoadbalancerProvider" 是服务的名称。
 * 这个名称必须与 Consul 或其他服务注册中心中注册的服务名称完全匹配(包括大小写),因为 Spring Cloud 会根据这个名称来查找和应用负载均衡策略。
 * 
 * configuration 属性:configuration = RestTemplateConfig.class 指定了该服务的负载均衡配置使用哪个配置类,这里指向的是当前的 RestTemplateConfig 类。
 * 通过这种方式,可以为特定的服务定制负载均衡策略,例如使用随机负载均衡(RandomLoadBalancer)而不是默认的轮询负载均衡(Round Robin)。
 */
@LoadBalancerClient(
        // 下面的value值大小写一定要和consul里面的名字一样,必须一样
        value = "LoadbalancerProvider", configuration = RestTemplateConfig.class)
public class RestTemplateConfig {
    /**
     * 这个注解用于启用客户端负载均衡功能。
     * 注解作用在 RestTemplate 上时,Spring 会为 RestTemplate 配置一个拦截器,
     * 这个拦截器会在你调用服务时自动根据服务名称(例如通过 Consul 注册中心注册的服务名)进行负载均衡。
     * 也就是说,当你在 RestTemplate 中使用服务名称来调用服务时,@LoadBalanced 会确保请求被分发到不同的服务实例上,以实现负载均衡。
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);

        return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }

}

image-20240826221944435

http://localhost:8888/consumer/66

19bec06c-c29f-4711-a3bb-c264468d64ff

三、环境搭建

SpringBoot+SpringCloud的版本:

<spring.boot.version>3.2.0</spring.boot.version>
<spring.cloud.version>2023.0.0</spring.cloud.version>

注册中心:

  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

Consul

image-20240823181110455

docker pull consul:1.9.6
docker run -d -p 8500:8500 --restart=always --name=consul -v /opt/consul:/consul/data consul:1.9.6 agent -server -bootstrap -ui -node=1 -client='0.0.0.0'
http://192.168.200.129:8500/ui/dc1/services

image-20240823180526926

jdk:

image-20240824171950942

Maven

image-20240823181810973

IDEA

image-20240823181906302

代码汇总:

https://github.com/shixiaochuangjob/markdownfile/tree/main/20240826

image-20240826222715629

在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部