当前位置: 代码网 > it编程>编程语言>Java > SpringCloud 负载均衡 spring-cloud-starter-loadbalancer

SpringCloud 负载均衡 spring-cloud-starter-loadbalancer

2024年08月02日 Java 我要评论
描述:除了内置的负载均衡策略外,spring-cloud-starter-loadbalancer 还支持自定义负载均衡策略。特点开发者可以根据实际需求实现自己的负载均衡算法。可以考虑服务实例的当前负载状态、性能、地理位置等多种因素来做出决策。提供了更高的灵活性和定制性。通过实现自定义的 ReactorLoadBalancer 来定义自己的负载均衡算法。定义自定义的负载均衡器。

简述

spring-cloud-starter-loadbalancer 是 spring cloud 中的一个组件,它提供了客户端负载均衡的功能。在 spring cloud 的早期版本中,netflix ribbon 被广泛用作客户端负载均衡器,但随着时间推移和 netflix ribbon 进入维护模式,spring cloud 社区开始转向更灵活、更易于维护的替代方案。

spring-cloud-starter-loadbalancer 是基于 spring 5 的 webclient 构建的,并使用了 reactor(spring 5 的反应式编程模型的核心库)来实现异步非阻塞的负载均衡请求。它与 spring cloud 的服务发现和配置结合得非常好,可以很容易地与 eureka、consul、nacos 等服务发现组件一起使用。

当将 spring-cloud-starter-loadbalancer 添加到spring boot 应用程序中时,可以使用 webclient.builder 的 loadbalancer 方法来创建一个具有负载均衡功能的 webclient 实例。这个 webclient 实例会自动从服务发现中获取服务实例列表,并使用内置的负载均衡算法(如轮询、随机等)来选择一个服务实例来发送请求。

例如,如果正在使用 eureka 作为服务发现,并且想要发送一个 get 请求到名为 “my-service” 的服务,可以这样做:

import org.springframework.beans.factory.annotation.autowired;  
import org.springframework.cloud.client.loadbalancer.loadbalanced;  
import org.springframework.context.annotation.bean;  
import org.springframework.stereotype.service;  
import org.springframework.web.reactive.function.client.webclient;  
  
@service  
public class myserviceclient {  
  
    @autowired  
    private webclient.builder webclientbuilder;  
  
    @bean  
    @loadbalanced  
    public webclient.builder loadbalancedwebclientbuilder() {  
        return webclient.builder();  
    }  
  
    public string getsomethingfrommyservice() {  
        // 注意这里我们直接使用了 "my-service" 作为 uri,而不是具体的服务实例地址  
        return webclientbuilder.build()  
                .get()  
                .uri("http://my-service/some-endpoint")  
                .retrieve()  
                .bodytomono(string.class)  
                .block(); // 注意:block() 方法会阻塞当前线程,通常只在非反应式上下文中使用  
    }  
}

主要特点

  • 基于 webclient:与 spring 5 的 webclient 紧密集成,提供了反应式(reactive)的 http 客户端功能。
  • 服务发现集成:与 spring cloud 的服务发现组件(如 eureka、consul、nacos 等)集成,可以自动获取服务实例列表。
  • 内置负载均衡算法:提供了内置的负载均衡算法,如轮询(round robin)、随机(random)等。
  • 反应式编程:支持反应式编程模型,允许非阻塞的 i/o 操作和异步处理。
  • 灵活性:与 ribbon 相比,提供了更多的灵活性和扩展性,可以更容易地定制负载均衡行为。
  • 与 spring cloud gateway 集成:与 spring cloud gateway 紧密集成,为其提供了负载均衡功能。

使用

  1. 添加依赖:在 maven 或 gradle 项目中添加 spring-cloud-starter-loadbalancer 依赖。
		<!-- springcloud loadbalancer -->
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-loadbalancer</artifactid>
        </dependency>
  1. 配置 webclient:使用 @loadbalanced 注解来标记一个 webclient.builder bean,以便将其配置为支持负载均衡。
  2. 发送请求:通过 webclient 发送请求时,使用服务名称(而不是具体的服务实例地址)作为 uri 的主机部分。
  3. 自定义负载均衡算法:如果需要,可以自定义负载均衡算法,并通过配置或编程方式将其应用到 webclient 上。

负载均衡算法

1. 轮询负载均衡策略(round robin)

  • 描述:这是默认的负载均衡策略,它会按照顺序依次将请求发送到服务实例列表中的每个服务实例。
  • 特点
    • 简单易实现。
    • 每个服务实例接收到的请求数量大致相等(在理想情况下)。
    • 不考虑服务实例的当前负载状态或性能。

2. 随机负载均衡策略(random)

  • 描述:该策略会随机选择一个服务实例来发送请求。
  • 特点
    • 在多次请求中,每个服务实例都有可能被选中。
    • 与轮询策略相比,它增加了随机性,但每个服务实例接收到的请求数量可能不均等。
    • 同样不考虑服务实例的当前负载状态或性能。

3. 自定义负载均衡策略

  • 描述:除了内置的负载均衡策略外,spring-cloud-starter-loadbalancer 还支持自定义负载均衡策略。
  • 特点
    • 开发者可以根据实际需求实现自己的负载均衡算法。
    • 可以考虑服务实例的当前负载状态、性能、地理位置等多种因素来做出决策。
    • 提供了更高的灵活性和定制性。

4. nacos 权重负载均衡器

  • 描述:当与 nacos 服务发现组件一起使用时,可以使用 nacos 提供的权重负载均衡器。
  • 特点
    • 服务实例可以配置权重值,权重值越高的实例接收到的请求越多。
    • 权重值可以根据服务实例的性能、资源使用情况等因素进行动态调整。
    • 提供了更细粒度的控制,可以根据实际需求进行灵活配置。

5. 自定义算法

通过实现自定义的 reactorloadbalancer 来定义自己的负载均衡算法。

  1. 定义自定义的负载均衡器:需要实现 reactorloadbalancer 接口或扩展现有的实现(如 roundrobinloadbalancer)。
  2. 实现 choose 方法:这是负载均衡算法的核心,它接收一个请求(通常是一个 request 对象)和一个服务实例列表(serviceinstancelistsupplier),并返回一个 mono,表示选定的服务实例。
  3. 配置自定义的负载均衡器:需要将自定义的负载均衡器配置为 spring cloud 的默认负载均衡器。这通常是通过注册一个 reactorloadbalancer 的 bean 来完成的。
    示例:
import org.springframework.cloud.client.serviceinstance;  
import org.springframework.cloud.client.loadbalancer.defaultrequest;  
import org.springframework.cloud.client.loadbalancer.reactiveloadbalancer;  
import org.springframework.cloud.client.loadbalancer.reactiveloadbalancerfactory;  
import org.springframework.cloud.client.serviceinstancechooser;  
import org.springframework.context.annotation.bean;  
import org.springframework.context.annotation.configuration;  
import reactor.core.publisher.mono;  
  
import java.util.list;  
  
@configuration  
public class customloadbalancerconfig {  
  
    @bean  
    public reactiveloadbalancer<serviceinstance> customloadbalancer(  
            reactiveloadbalancerfactory<serviceinstance> factory,  
            objectprovider<list<serviceinstance>> serviceinstances) {  
  
        return new reactiveloadbalancer<serviceinstance>() {  
  
            @override  
            public mono<response<serviceinstance>> choose(request request) {  
                // 这里是自定义的负载均衡算法实现  
                // 例如,我们可以简单地返回服务实例列表中的第一个实例  
                return mono.justorempty(serviceinstances.getifavailable())  
                        .flatmapmany(list::stream)  
                        .firstelement() // 或者可以实现自己的选择逻辑  
                        .map(response::just);  
            }  
  
            // 其他必要的方法(如 recordstats, filter, etc.)可以根据需要进行实现  
        };  
    }  
  
    // 如果想要为特定的服务配置自定义的负载均衡器,  
    // 可以通过 serviceid 来区分并返回不同的 reactiveloadbalancer 实例  
    // 例如,public reactiveloadbalancer<serviceinstance> customloadbalancerforservicex(...) {...}  
}

反应式编程

从 spring cloud greenwich 版本开始,spring cloud 引入了对 project reactor 的支持,并将负载均衡器从传统的阻塞式(基于 ribbon)转变为反应式(基于 spring-cloud-starter-loadbalancer)。

反应式编程是一种异步、非阻塞的编程范式,它使用数据流(streams)和变化传播(propagation of change)来处理数据。在反应式编程中,数据不是通过传统的调用和返回机制来传递的,而是通过异步数据流在组件之间传递。

在 spring-cloud-starter-loadbalancer 中,反应式编程主要体现在以下几个方面:

  1. 非阻塞调用:与传统的基于 ribbon 的阻塞式负载均衡器不同,spring-cloud-starter-loadbalancer 使用反应式编程模型来执行非阻塞的负载均衡请求。这意味着它不会阻塞线程等待响应,而是异步地处理请求和响应。
  2. 响应式类型:负载均衡器的 api 使用了反应式类型,如 mono 和 flux,它们是 project reactor 提供的反应式类型。mono 用于表示 0 或 1 个元素的异步序列,而 flux 用于表示 0 到 n 个元素的异步序列。
  3. 背压(backpressure):反应式编程支持背压机制,即消费者可以控制生产者生成数据的速度。这在处理大量并发请求时非常有用,可以避免因生产者过快生成数据而导致消费者处理不过来。
  4. 错误处理:反应式编程提供了丰富的错误处理机制,如 onerrorresume、retry 等操作符,可以在发生错误时优雅地处理异常情况。
  5. 组合和转换:mono 和 flux 提供了丰富的操作符,用于组合和转换异步数据流。这使得可以灵活地处理负载均衡请求和响应,满足各种复杂的业务需求。
    简单的示例:
import org.springframework.cloud.client.serviceinstance;  
import org.springframework.cloud.client.loadbalancer.loadbalancerclient;  
import org.springframework.web.bind.annotation.getmapping;  
import org.springframework.web.bind.annotation.restcontroller;  
import org.springframework.web.reactive.function.client.webclient;  
  
import reactor.core.publisher.mono;  
  
@restcontroller  
public class mycontroller {  
  
    private final loadbalancerclient loadbalancerclient;  
  
    public mycontroller(loadbalancerclient loadbalancerclient) {  
        this.loadbalancerclient = loadbalancerclient;  
    }  
  
    @getmapping("/call-service")  
    public mono<string> callservice() {  
        // 获取服务实例  
        serviceinstance serviceinstance = loadbalancerclient.choose("my-service").block();  
  
        // 使用 webclient 发起反应式请求  
        webclient webclient = webclient.builder()  
                .baseurl(serviceinstance.geturi().tostring())  
                .build();  
  
        return webclient.get()  
                .uri("/some-endpoint")  
                .retrieve()  
                .bodytomono(string.class);  
    }  
}

与 openfeign 集成

spring cloud 应用程序中,spring-cloud-starter-loadbalancer 通常与 spring-cloud-starter-openfeign 或其他 http 客户端(如 webclient)一起使用,以支持对服务发现的客户端进行负载均衡的调用。
当使用 openfeign 声明式 http 客户端时,spring-cloud-starter-loadbalancer 会自动集成以提供负载均衡功能。只需在 pom.xml 或 build.gradle 文件中包含相应的依赖,并在 feign 客户端接口上使用 @feignclient 注解指定服务名。
maven 依赖

<dependencies>  
   <!-- ... 其他依赖 ... -->  
   <dependency>  
       <groupid>org.springframework.cloud</groupid>  
       <artifactid>spring-cloud-starter-openfeign</artifactid>  
   </dependency>  
   <dependency>  
       <groupid>org.springframework.cloud</groupid>  
       <artifactid>spring-cloud-starter-loadbalancer</artifactid>  
   </dependency>  
   <!-- ... 其他依赖 ... -->  
</dependencies>

feign 客户端

@feignclient(name = "my-service")  
public interface myserviceclient {  
   // 定义 http 方法  
   @getmapping("/some-endpoint")  
   mono<string> getsomething();  
}

webclient 集成

使用 webclient 作为 http 客户端,可以通过 spring-cloud-starter-loadbalancer 来实现服务间的负载均衡调用。需要创建一个 webclient.builder bean,并使用 loadbalancerexchangefilterfunction 来自动处理服务发现和负载均衡。
配置 webclient bean

@bean  
public webclient.builder webclientbuilder(loadbalancerclient loadbalancerclient) {  
    return webclient.builder()  
            .baseurl("lb://my-service") // 使用 'lb://' 前缀启用负载均衡  
            .filter(new loadbalancerexchangefilterfunction(loadbalancerclient));  
}

使用 webclient 发起请求

@autowired  
private webclient.builder webclientbuilder;  
  
public mono<string> callservice() {  
    webclient webclient = webclientbuilder.build();  
    return webclient.get()  
            .uri("/some-endpoint")  
            .retrieve()  
            .bodytomono(string.class);  
}
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com