使用 Spring Cloud Loadbalancer 实现客户端负载均衡

使用,spring,cloud,loadbalancer,实现,客户端,负载,均衡 · 浏览次数 : 841

小编点评

**使用 Spring Cloud Loadbalancer 实现客户端负载均衡** Spring Cloud Loadbalancer 是一个在客户端实现负载均衡策略的负载均衡器。 **配置 Spring Cloud Loadbalancer** 1. 在项目配置中添加 LoadBalancerClient 注解: ```java @LoadBalancerClient(name = "server") public class WebClientConfig { // ... } ``` 2. 配置负载均衡器: ```java @Bean @Primary ServiceInstanceListSupplier serviceInstanceListSupplier() { return new ServiceInstanceListSupplier() { @Override public String getServiceId() { return "server"; } @Override public Flux get() { return Flux.just(Arrays.asList( new DefaultServiceInstance("server1", "server", "localhost", 8090, false), new DefaultServiceInstance("server2", "server", "localhost", 9092, false), new DefaultServiceInstance("server3", "server", "localhost", 9999, false) )); } }; } ``` **配置 WebClient** ```java @Bean public WebClient.Builder loadBalancedWebClientBuilder() { return WebClient.builder(); } @Bean @Primary WebClient webClient() { return loadBalancedWebClientBuilder.build(); } ``` **使用** 在任何 Controller 中,可以使用 `WebClient.get()` 或 `WebClient.post()` 等方法访问服务。 **示例** ```java @RestController public class HiController { private final WebClient webClient; public HiController(WebClient.Builder loadBalancedWebClientBuilder) { this.webClient = loadBalancedWebClientBuilder.build(); } @RequestMapping("/hi") public Mono hi(@RequestParam(value = "name", defaultValue = "Mary") String name) { return webClient.get().uri("http://server/greeting").retrieve().bodyToMono(String.class).map(greeting -> String.format("%s, %s!", greeting, name)); } } ``` **运行** 在本地启动服务器,并使用 IDEA 等 IDE 创建一个新的 Spring Boot 项目,并将其部署到 Spring Cloud 服务器上。运行 `ClientApplication` 启动客户端。访问 `http://localhost:8888/hi`,它应该轮流从三个服务实例中获取请求。

正文

使用 Spring Cloud Loadbalancer 实现客户端负载均衡

作者:Grey

原文地址:

博客园:使用 Spring Cloud Loadbalancer 实现客户端负载均衡

CSDN:使用 Spring Cloud Loadbalancer 实现客户端负载均衡

背景

Spring Cloud G 版发布时提到,
Spring Cloud Netflix 那套组件很多都进入了维护期,如下表所示

image

同时,针对一些组件,Spring 官方给出了一些替代方案

image

针对 spring-cloud-ribbon 这个负载均衡组件,Spring 官方提出的替换解决方案是 Spring Cloud Loadbalancer。本文主要通过一个示例介绍了 Spring Cloud Loadbalancer 的基础使用。

环境

  • JDK 1.8+

  • Maven 3.5+

  • Spring Boot 版本:2.7.5

  • Spring Cloud 版本:2021.0.5

项目结构和说明

  • spring-cloud-loadbalanced-usage:父项目名称
    • server : 服务端端模块
      • src/
      • pom.xml
    • client : 客户端模块
      • src/
      • pom.xml
    • pom.xml:父项目 pom 配置

流程

整个过程如下示例图

image

注:Spring Cloud Loadbalancer 是在客户端实现负载均衡策略。

代码说明

服务端主要暴露一个服务,未做特殊配置

    @GetMapping("/greeting")
    public String greet() {
        log.info("Access /greeting");
        int randomNum = rand.nextInt(greetings.size());
        return greetings.get(randomNum);
    }

客户端的核心配置如下,主要是针对负载均衡配置:

package git.snippet.client.config;

import org.springframework.cloud.client.DefaultServiceInstance;
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.ServiceInstanceListSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

import java.util.Arrays;
import java.util.List;

@Configuration
@LoadBalancerClient(name = "server")
public class WebClientConfig {

    @LoadBalanced
    @Bean
    WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }

    @Bean
    @Primary
    ServiceInstanceListSupplier serviceInstanceListSupplier() {
        return new ServiceInstanceListSupplier() {
            @Override
            public String getServiceId() {
                return "server";
            }

            @Override
            public Flux<List<ServiceInstance>> get() {
                return Flux.just(Arrays.asList(
                        new DefaultServiceInstance(getServiceId() + "1", getServiceId(), "localhost", 8090, false),

                        new DefaultServiceInstance(getServiceId() + "2", getServiceId(), "localhost", 9092, false),

                        new DefaultServiceInstance(getServiceId() + "3", getServiceId(), "localhost", 9999, false)));
            }
        };
    }
}

其中 @LoadBalancerClient(name = "server") 指定了 服务端的名称;

getServiceId()指定了服务端的服务 ID;

serviceInstanceListSupplier()方法中列出了三个服务端实例的地址;

new DefaultServiceInstance(getServiceId() + "1", getServiceId(), "localhost", 8090, false)
new DefaultServiceInstance(getServiceId() + "2", getServiceId(), "localhost", 9092, false)
new DefaultServiceInstance(getServiceId() + "3", getServiceId(), "localhost", 9999, false)

有了这个配置,在客户端的 Controller 中,做如下注入即可

package git.snippet.client.controller;

import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@RestController
public class HiController {
    private final WebClient.Builder loadBalancedWebClientBuilder;
    private final ReactorLoadBalancerExchangeFilterFunction lbFunction;


    public HiController(WebClient.Builder loadBalancedWebClientBuilder, ReactorLoadBalancerExchangeFilterFunction lbFunction) {
        this.loadBalancedWebClientBuilder = loadBalancedWebClientBuilder;
        this.lbFunction = lbFunction;
    }

    @RequestMapping("/hi")
    public Mono<String> hi(@RequestParam(value = "name", defaultValue = "Mary") String name) {
        return loadBalancedWebClientBuilder.build().get().uri("http://server/greeting").retrieve().bodyToMono(String.class).map(greeting -> String.format("%s, %s!", greeting, name));
    }

    @RequestMapping("/hello")
    public Mono<String> hello(@RequestParam(value = "name", defaultValue = "John") String name) {
        return WebClient.builder().filter(lbFunction).build().get().uri("http://server/greeting").retrieve().bodyToMono(String.class).map(greeting -> String.format("%s, %s!", greeting, name));
    }
}

启动并测试

首先启动 server,注意:

启动 server 的时候,需要启动多实例,且每个实例要定义 VM options

实例一定义 VM options 为 -Dserver.port=8090

实例二定义 VM options 为 -Dserver.port=9092

实例三定义 VM options 为 -Dserver.port=9999

如果使用 IDEA Intellij,配置方式如下

image

三个 Server 启动后,接下来启动 client,运行 ClientApplication,启动完毕后,多次访问: http://localhost:8888/hi

可以通过每个 server 实例的运行日志,查看到每个实例都轮流获取到了请求,实现了负载均衡。

完整代码

见:spring-cloud-loadbalancer-usage

参考文档

Spring Tips: Spring Cloud Loadbalancer

Spring Cloud Greenwich.RELEASE is now available

Client-Side Load-Balancing with Spring Cloud LoadBalancer

与使用 Spring Cloud Loadbalancer 实现客户端负载均衡相似的内容:

使用 Spring Cloud Loadbalancer 实现客户端负载均衡

使用 Spring Cloud Loadbalancer 实现客户端负载均衡 作者:Grey 原文地址: 博客园:使用 Spring Cloud Loadbalancer 实现客户端负载均衡 CSDN:使用 Spring Cloud Loadbalancer 实现客户端负载均衡 背景 在Spring

【Azure Service Bus】使用Spring Cloud integration示例代码,为多个 Service Bus的连接使用 ConnectionString 方式

问题描述 查看Service Bus的Java示例代码,发现使用Spring Cloud Integration,配置 Application.yaml 可以连接到两个Service Bus。 但代码中没有使用Connection String 属性配置服务连接。 那么,是否可以直接在此添加 con

Spring Cloud Circuit Breaker 使用示例

Spring Cloud Circuit Breaker 使用示例 作者: Grey 原文地址: 博客园:Spring Cloud Circuit Breaker 使用示例 CSDN:Spring Cloud Circuit Breaker 使用示例 说明 Spring Cloud Circuit

Spring Cloud Gateway 使用示例

Spring Cloud Gateway 使用示例 作者: Grey 原文地址: 博客园:Spring Cloud Gateway 使用示例 CSDN:Spring Cloud Gateway 使用示例 说明 Spring Cloud Gateway 用于构建 API 网关,基于 Spring We

Spring Cloud 部署时如何使用 Kubernetes 作为注册中心和配置中心

一、Spring Cloud 支持的常见注册中心和配置中心。 Spring Cloud 自带的注册中心Eureka以及config配置中心 Nacos,支持注册中心和配置中心等,可以参考:https://www.cnblogs.com/laoqing/p/17797759.html Zookeepe

[转帖]Spring Cloud Alibaba Nacos 注册中心使用教程

一. 什么是Nacos Nacos是一个更易于构建云原生应用的动态服务发现(Nacos Discovery )、服务配置(Nacos Config)和服务管理平台,集注册中心+配置中心+服务管理于一身,基本特性如下: 服务发现和服务健康监测; 动态配置服务; 动态 DNS 服务; 服务及其元数据管理

Apollo2.1.0+Springboot使用OpenApI

## 依赖管理 ```xml org.springframework.cloud spring-cloud-starter-bootstrap 3.1.3 com.ctrip.framework.apollo apollo-client 2.1.0 com.ctrip.framework.apoll

[转帖]k8s发布Spring cloud+eureka架构服务优雅启动停止方案

本文转载自昆仑枫的简书https://www.jianshu.com/p/6d393cbb694a Spring cloud+eureka是目前微服务主流解决方案之一,kubernetes则是广泛应用的发布工具,两者结合使用很常见。而两者结合时如何优雅启停从而实现无感发布很关键。下面将从不做特殊处理

[转帖]Spring Cloud 整合 SkyWalking

https://www.jianshu.com/p/e81e35dc6406 Java Agent 服务器探针 探针,用来收集和发送数据到归集器。参考官网给出的帮助 Setup java agent,我们需要使用官方提供的探针为我们达到监控的目的,按照实际情况我们需要实现三种部署方式 IDEA 部署

[转帖]拜托!面试请不要再问我Spring Cloud底层原理

https://www.cnblogs.com/jajian/p/9973555.html 概述# 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术。不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓。因此