写点什么

SpringCloudAliBaba 组件之 Ribbon 精讲【负载均衡】

作者:XiaoLin_Java
  • 2021 年 12 月 01 日
  • 本文字数:2137 字

    阅读完需:约 7 分钟

SpringCloudAliBaba 组件之 Ribbon精讲【负载均衡】

📢博客主页:https://www.infoq.cn/profile/F7BF297568FAA8/publish

📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论!

📢本文由 XiaoLin_Java 原创🙉

📢不要等待机会,而要创造机会。✨

🌈往期回顾

感谢阅读,希望能对你有所帮助,博文若有瑕疵请在评论区留言或在主页个人介绍中添加我私聊我,感谢每一位小伙伴不吝赐教。我是 XiaoLin,一个问啥啥都会,干啥啥不行的小男孩。

六、负载均衡:Ribbon

6.1、负载均衡简介

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


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


  1. 服务端负载均衡指的是发生在服务提供者一方,比如常见的 nginx 负载均衡。

  2. 客户端负载均衡指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求。



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

6.2、手动实现负载均衡

6.2.1、起一个不同端口的服务

    我们需要借助 IDEA 再启一个服务,这个服务也是 ShopProductServer,但是他的端口是不同的。


    在 VM option 中输入需要指定的端口号即可:


-Dserver.port=8081
复制代码



6.2.2、修改实现类代码实现负载均衡

 @Override  public Order getById(Long oid, Long pid) {    // 从nacos中获取服务    List<ServiceInstance> instances = discoveryClient.getInstances("product-service");    // 定义一个随机数    int index = new Random().nextInt(instances.size());    // 随机获取一个服务    ServiceInstance serviceInstance = instances.get(index);    String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();    Product product = restTemplate        .getForObject("http://"+url+"/product?productId=" + pid, Product.class);    Order order = orderDao.getOne(oid);    order.setUsername(order.getUsername()+",data form "+serviceInstance.getPort());    return order;  }
复制代码


连续测试多几次就可以发现随机的负载均衡策略实现了。



6.3、基于 Ribbon 实现负载均衡

6.3.1、Ribbon 是什么

    Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等。**Ribbon 就是简化了上面代码的组件,其中提供了更多的负载均衡算法。**它是 Spring Cloud 的一个组件,它可以让我们使用一个注解就能轻松的搞定负载均衡。

6.3.2、Ribbon 实现负载均衡

6.3.2.1、添加注解

    我们需要在 RestTemplate 的生成方法上添加一个注解:@LoadBalance,这个注解是一个增强注解,它可以增强 RestTemplate ,使他可以实现负载均衡。


  @Bean  @LoadBalanced  public RestTemplate getInstance(){    return new RestTemplate();  }
复制代码

6.3.2.2、修改 ProductService 实现类的代码

    为了更直观,我们直接 1 将 application.yml 中的端口号设置到实现类中。


  @Value("${server.port}")  private String port;
@Override public Product findById(Long productId) { Product product = productDao.findById(productId).get(); product.setPname(product.getPname()+",data form"+port); return product; }
复制代码



6.3.2.3、修改 OrderService 实现类的代码

  @Override  public Order getById(Long oid, Long pid) {    Product product = restTemplate        .getForObject("http://product-service/product?productId=" + pid, Product.class);    Order order = orderDao.getOne(oid);    order.setPname(product.getPname());    return order;  }
复制代码

6.3.2.4、实现原理

    为什么使用服务的名称替代 url 就可以实现负载均衡了呢?


  1. 通过反射获取到你传递过来的参数(假设传进来 1),此时的 url 变成了:http://product-service/product?productId=1.

  2. 按照规则进行切割,将 product-service 切割出来。

  3. 根据从注册中心拉去过来的服务列表对应着的节点信息,假设 1product-service 对应着 192.168.10.180:8081 和 192.168.10.180:8083。

  4. 根据你 1 配置的负载均衡的策略去选择一个信息节点,将服务名称替换成对应的 ip 和端口。假设此时 url 变成了:


http://192.168.10.180:8081/product?productId=1


  1. 使用 RestTemplate 去发送请求。


    注意:一定要在 RestTemplate 的生成方法上添加 @LoadBalance 注解,这个注解表示将 RestTemplate 进行加强,只有进行了加强才会去实现上述的步骤,不然是无法实现负载均衡的。

6.4、Ribbon 支持的负载均衡策略

    Ribbon 内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule,他具体支持的负载均衡策略有:



我们可以通过修改配置来调整 Ribbon 的负载均衡策略,在 Shop-order-server 项目的 application.yml 中增加如下配置:


product-service: # 调用的提供者的名称  ribbon:    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
复制代码


发布于: 4 小时前阅读数: 6
用户头像

XiaoLin_Java

关注

问啥啥都会,干啥啥不行。 2021.11.08 加入

问啥啥都会,干啥啥不行。CSDN原力作者,掘金优秀创作者。

评论

发布
暂无评论
SpringCloudAliBaba 组件之 Ribbon精讲【负载均衡】