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

作者:Grey

原文地址:

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

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

背景

Spring Cloud G 版发布时提到,

Spring Cloud Netflix 那套组件很多都进入了维护期,如下表所示

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

针对 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 配置

流程

整个过程如下示例图

注: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,配置方式如下

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

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

完整代码

见:spring-cloud-loadbalancer-usage

参考文档

Spring Cloud Greenwich.RELEASE is now available

Client-Side Load-Balancing with Spring Cloud LoadBalancer

使用 Spring Cloud LoadBalancer 实现客户端负载均衡的更多相关文章

  1. 服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)

    在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一 ...

  2. Spring Cloud Ribbon实现客户端负载均衡

    1.构建microservice-consumer-movie-ribbon项目,在pom.xml中引入ribbon依赖 在引入Eureka依赖的时候,默认里面含有ribbon依赖 2.添加@Load ...

  3. Spring Cloud 客服端负载均衡 Ribbon

    一.简介   Spring Cloud Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的.它不像服务注册中心.配置中心.API网关那样独立部署, ...

  4. Spring Cloud - 切换Ribbon的负载均衡模式

    Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模 ...

  5. 2.【Spring Cloud Alibaba】实现负载均衡-Ribbon

    负载均衡的两种方式 如何实现负载均衡 目前已经实现让A总能找到B,如何实现负载均衡 负载均衡的两种方式 服务器端负载均衡 客户端负载均衡 使用Ribbo实现负载均衡 Ribbon是什么 ==Netfl ...

  6. Spring Cloud微服务Ribbon负载均衡/Zuul网关使用

    客户端负载均衡,当服务节点出现问题时进行调节或是在正常情况下进行 服务调度.所谓的负载均衡,就是当服务提供的数量和调用方对服务进行 取舍的调节问题,在spring cloud中是通过Ribbon来解决 ...

  7. 4.Spring Cloud初相识--------Feign负载均衡

    前言: 在上一节里,我们学习了ribbon的使用. 我们了解到ribbon是一个客户端负载均衡机制. 而我们今天要讲的Feign呢,也是一款客户端负载均衡机制. 或者这样说,Feign封装了ribbo ...

  8. 撸一撸Spring Cloud Ribbon的原理-负载均衡策略

    在前两篇<撸一撸Spring Cloud Ribbon的原理>,<撸一撸Spring Cloud Ribbon的原理-负载均衡器>中,整理了Ribbon如何通过负载均衡拦截器植 ...

  9. Spring Cloud Gateway Ribbon 自定义负载均衡

    在微服务开发中,使用Spring Cloud Gateway做为服务的网关,网关后面启动N个业务服务.但是有这样一个需求,同一个用户的操作,有时候需要保证顺序性,如果使用默认负载均衡策略,同一个用户的 ...

  10. 【Spring Cloud学习之三】负载均衡

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 主流的负载均衡技术有nginx.LVS.HAproxy.F5,Spring Clou ...

随机推荐

  1. Linux有趣命令

    通外网 下载使用阿里云镜像源:wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.re ...

  2. HDFS 伪分布式环境搭建

    HDFS 伪分布式环境搭建 作者:Grey 原文地址: 博客园:HDFS 伪分布式环境搭建 CSDN:HDFS 伪分布式环境搭建 相关软件版本 Hadoop 2.6.5 CentOS 7 Oracle ...

  3. Job And Schedule (V8R6C4)

    KingbaseES 数据库提供了 kdb_schedule 扩展,使得用户能通过类似oracle job 的方式进行job调用.kdb_schedule 提供了三个Schema :dbms_job ...

  4. Kibana管理

    这里是用来管理您的 kibana 运行时配置的地方,包括初始化配置和后续的索引模式配置.高级设置等.您可以调整 kibana 自身的行为,也可以编辑您通过 kibana 保存的查询.视图.仪表板等各种 ...

  5. DophineSheduler上下游任务之间动态传参案例及易错点总结

    ​   作者简介 ​ 淡丹 数仓开发工程师 5年数仓开发经验,目前主要负责百得利MOBY新车业务 二手车业务及售后服务业务系统数仓建设   业务需求 在ETL任务之间调度时,我们有的时候会需要将上游的 ...

  6. C++ 自学笔记 对象的初始化

    数组的初始化: 在 C++中  struct ≈ Class:struct里面可以有函数. 默认构造函数: 没有参数的构造函数就是默认构造函数

  7. 轻量级Web框架Flask——Web表单

    安装 Flask-WTF及其依赖可使用pip安装 pip install flask_wtf 配置 要求应用配置一个密钥.密钥是一个由随机字符构成的唯一字符串,通过加密或签名以不同的方式提升应用的安全 ...

  8. C语言下for循环的一点技巧总结

    for循环是普遍应用与各种计算机语言的一种循环方式. 一般情况下, for循环规则:for(条件一:条件二:条件三) 条件一为满足条件,也就是条件一为1时,进入这个for循环.条件二为循环条件,也就是 ...

  9. 使用 Spring Security 手动验证用户

    1.概述 在这篇快速文章中,我们将重点介绍如何在 Spring Security 和 Spring MVC 中手动验证用户的身份. 2.Spring Security 简单地说,Spring Secu ...

  10. linux下rsync的同步

    rsync是linux系统下的数据镜像备份工具.使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH.rsync****主机同步 文件下载地址: 链接:https:/ ...