【Spring Cloud】实现微服务调用的负载均衡
作者:mmseoamin日期:2024-02-24

文章目录

  • 什么是负载均衡
  • 自定义实现负载均衡
    • 启动shop-product微服务
    • 通过nacos查看微服务的启动情况
    • 自定义实现负载均衡
    • 基于Ribbon实现负载均衡
      • 添加注解
      • 修改服务调用的方法
      • Ribbon支持的负载均衡策略
        • 通过修改配置来调整 Ribbon 的负载均衡策略
        • 通过注入Bean来调整 Ribbon 的负载均衡策略
        • 饥饿加载
        • 总结

          欢迎来到阿Q社区

          https://bbs.csdn.net/topics/617897123

          什么是负载均衡

          通俗的讲,负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

          根据负载均衡发生位置的不同,一般分为服务端负载均衡和客户端负载均衡。

          • 服务端负载均衡指的是发生在服务提供者一方,比如常见的 nginx 负载均衡。
          • 客户端负载均衡指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求。

            【Spring Cloud】实现微服务调用的负载均衡,在这里插入图片描述,第1张

            我们在微服务调用关系中一般会选择客户端负载均衡,也就是在服务调用的一方来决定服务由哪个提供者执行。

            自定义实现负载均衡

            启动shop-product微服务

            在启动 shop-product 微服务的基础上,通过idea再启动一个 shop-product 微服务,设置其端口为8082。

            【Spring Cloud】实现微服务调用的负载均衡,在这里插入图片描述,第2张

            命令为-Dserver.port=8082

            通过nacos查看微服务的启动情况

            【Spring Cloud】实现微服务调用的负载均衡,在这里插入图片描述,第3张

            自定义实现负载均衡

            修改 shop-order 的代码

            public ShopOrder order(@PathVariable("pid") Long pid) {
                    log.info("客户下单,这时候要调用商品微服务查询商品信息。。。");
                    //从nacos中获取服务地址
                    List instances = discoveryClient.getInstances("shop-product");
                    //自定义规则实现随机挑选服务
                    int index = new Random().nextInt(instances.size());
                    ServiceInstance serviceInstance = instances.get(index);
                    String url = serviceInstance.getHost()+":"+serviceInstance.getPort();
                    log.info(">>从nacos中获取到的微服务地址为:"+ url);
                    //通过restTemplate调用商品微服务
                    ShopProduct shopProduct = restTemplate.getForObject("http://"+url+"/product/"+pid, ShopProduct.class);
                    log.info("当前用户信息为自己,假设我们设置为1");
                    ShopOrder shopOrder = new ShopOrder();
                    shopOrder.setUid(1L);
                    shopOrder.setUsername("公众号:阿Q说代码");
                    shopOrder.setPid(shopProduct.getId());
                    shopOrder.setPname(shopProduct.getPname());
                    orderService.save(shopOrder);
                    //商品扣减库存的逻辑
                    ProductReduceDTO productReduceDTO = new ProductReduceDTO();
                    productReduceDTO.setProductId(pid);
                    productReduceDTO.setReductCount(1);
                    Integer count = restTemplate.postForObject("http://"+url+"/product/reduceStock", productReduceDTO, Integer.class);
                    return shopOrder;
                }
            

            启动两个服务提供者和一个服务消费者,多访问几次消费者,测试效果:

            【Spring Cloud】实现微服务调用的负载均衡,在这里插入图片描述,第4张

            基于Ribbon实现负载均衡

            Ribbon 是Spring Cloud的一个组件,它可以让我们使用一个注解就能轻松的搞定负载均衡。

            添加注解

            在 RestTemplate 的生成方法上添加@LoadBalanced注解

            @Bean
            @LoadBalanced
             public RestTemplate getRestTemplate() {
                 return new RestTemplate();
             }
            

            修改服务调用的方法

            将上一步中的代码注释掉,改为直接使用微服务名字,从nacos中获取服务地址

            //从nacos中获取服务地址
            //自定义规则实现随机挑选服务
            //List instances = discoveryClient.getInstances("shop-product");
            //int index = new Random().nextInt(instances.size());
            //ServiceInstance serviceInstance = instances.get(index);
            //String url = serviceInstance.getHost()+":"+serviceInstance.getPort();
            //直接使用微服务名字,从nacos中获取服务地址
            String url="shop-product";
            

            重启服务进行测试,微服务调用成功。

            Ribbon支持的负载均衡策略

            Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule,具体的负载策略如下图所示:

            【Spring Cloud】实现微服务调用的负载均衡,在这里插入图片描述,第5张

            通过修改配置来调整 Ribbon 的负载均衡策略

            # 负载均衡规则
            shop-product:
              ribbon:
                NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
            

            通过注入Bean来调整 Ribbon 的负载均衡策略

             @Bean
             public IRule randomRule(){
                 return new RandomRule();
             }
            

            饥饿加载

            为何要开启饥饿加载,因为在我们第一次加载时候,响应时间比较慢,原因是第一次加服务需要从服务注册列表中拉取服务实例,以及初始化相关的组件到 Spring 中。

            开启饥饿加载的相关配置之后这些操作会在服务启动就会完成。

            ribbon:
              eager-load:
                clients:
                  - shop-product
            

            总结

            到这儿,我们微服务调用的负载均衡实现就结束了。下一篇将为大家带来基于feign实现微服务调用的文章,敬请期待吧!

            后续的文章,我们将继续完善我们的微服务系统,集成更多的Alibaba组件。想要了解更多JAVA后端知识,请点击文末名片与我交流吧。留下您的一键三连,让我们在这个寒冷的东西互相温暖吧!