• 微服务负载均衡器LoadBalancer实战


    1.什么是Spring Cloud LoadBalancer

    Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器, 用来替代Ribbon。

    Spring官方提供了两种负载均衡的客户端:

    RestTemplate

    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。

    WebClient

    WebClient是从Spring WebFlux 5.0版本开始提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具。它的响应式编程的基于Reactor的。WebClient中提供了标准Http请求方式对应的get、post、put、delete等方法,可以用来发起相应的请求。

    2.RestTemplate整合LoadBalancer

    RestTemplate、WebClient 整合LoadBalancer详细项目请参考:https://gitee.com/tea-Sir/spring-cloud-alibaba.git

    1)引入依赖

     <dependencies>
            <!-- LoadBalancer -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            </dependency>
    
            <!-- 提供了RestTemplate支持 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- nacos服务注册与发现 -->
            <!‐‐ nacos服务注册与发现 移除ribbon支持‐‐>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意: nacos-discovery中引入了ribbon,需要移除ribbon的包

    如果不移除,也可以在yml中配置不使用ribbon

    spring:
      application:
        name: mall-user-loadbalancer-demo
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
        # 不使用ribbon
        loadbalancer:
          ribbon:
            enabled: false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    原理:默认情况下,如果同时拥有RibbonLoadBalancerClient和BlockingLoadBalancerClient,为了保持向后兼容性,将使用RibbonLoadBalancerClient。要覆盖它,可以设置spring.cloud.loadbalancer.ribbon.enabled属性为false。

    2)使用@LoadBalanced注解配置RestTemplate

     @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3) 使用

    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @RequestMapping(value = "/findOrderByUserId/{id}")
        public R findOrderByUserId(@PathVariable("id") Integer id) {
    
            String url = "http://mall-order/order/findOrderByUserId/"+id;
            //基于RestTemplate
            R result = restTemplate.getForObject(url,R.class);
    
            return result;
        }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    3.WebClient整合LoadBalancer

    1)引入依赖

     <dependencies>
            <!-- LoadBalancer -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-webflux</artifactId>
            </dependency>
    
            <!-- nacos服务注册与发现 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2) 配置WebClient作为负载均衡器的client

    @Configuration
    public class WebClientConfig {
    
      @LoadBalanced
      @Bean
      WebClient.Builder webClientBuilder() {
        return WebClient.builder();
      }
    
    
      @Bean
      WebClient webClient() {
        return webClientBuilder().build();
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3) 使用

     @Autowired
        private WebClient webClient;
    
        @RequestMapping(value = "/findOrderByUserId2/{id}")
        public Mono<R> findOrderByUserIdWithWebClient(@PathVariable("id") Integer id) {
    
            String url = "http://mall-order/order/findOrderByUserId/"+id;
            //基于WebClient
            Mono<R> result = webClient.get().uri(url)
                    .retrieve().bodyToMono(R.class);
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    原理: 底层会使用ReactiveLoadBalancer
    在这里插入图片描述

    引入webFlux

    @Autowired
    private ReactorLoadBalancerExchangeFilterFunction lbFunction;
    
    @RequestMapping(value = "/findOrderByUserId3/{id}")
    public Mono<R> findOrderByUserIdWithWebFlux(@PathVariable("id") Integer id) {
    
        String url = "http://mall-order/order/findOrderByUserId/"+id;
        //基于WebClient+webFlux
        Mono<R> result = WebClient.builder()
                .filter(lbFunction)
                .build()
                .get()
                .uri(url)
                .retrieve()
                .bodyToMono(R.class);
        return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    4.RestTemplate和WebClient区别

    使用webClient在等待响应的同时不会阻塞正在执行的线程 ;这种异步编程的方式避免了线程阻塞,线程处理完一个请求紧接着可以处理下一个,能够提高系统的吞吐量;而restTemplate 这种方式是阻塞的,会一直占用当前线程资源,直到http返回响应。如果等待的请求发生了堆积,应用程序将创建大量线程,直至耗尽线程池和所有可用内存。同时伴随着频繁的CPU上下文切换,可能导致性能下降。

    但是作为上述两种方式的调用者(消费者)而言,其最终获得http响应结果的耗时并未减少。比如浏览器访问上述ProductController 的两个接口时,返回数据的耗时相同。最终获取(消费)数据的地方还会等待。

    使用webclient替代restTemplate的好处是可以异步等待http响应,使得线程不需要阻塞;单位时间内有限资源下支持更高的并发量。

    总结

    1、Spring Cloud官方自己提供的客户端负载均衡器中,建议采用WebClient作为异步响应式Http请求客户端工具。

    WebClient发送Http请求支持异步响应,无需阻塞线程,相同条件下支持更高的并发。

  • 相关阅读:
    Java中的ArrayList和LinkedList的区别
    【Spring框架学习3】Spring Bean的作用域 及 生命周期
    Vega Prime入门教程14.01:调用VAPS XT DLL
    Golang在Web应用程序开发中的优势和适用性
    聊一聊Spring 事务的相关操作
    揭秘:如何只用一个软件分析股市数据?
    SpringBoot整合第三方技术----缓存、任务、邮件、消息
    视频处理工具安利,要制作视频的快来
    把backtrader改造成金融强化学习回测引擎
    论文选题分享及思路(一)《基于C51单片机的自动化测量产线的设计》
  • 原文地址:https://blog.csdn.net/qq_36109477/article/details/126130049