微服务系列--Ribbon负载均衡

超、凢脫俗 2022-09-05 06:00 317阅读 0赞

1、前言

这篇文章接上一篇文章进行开发,上一篇整合完了Nacos,这篇来整合Ribbon。Ribbon不属于SpringCloud Alibaba的东西,而是基于Netflix Ribbon实现的。可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。

2、核心注解

Rabbin的依赖不需要进行重复导入,因为我们上一篇在导入nacos的时候,其实就已经导入进来了,nacos引入的相关依赖里面,包含了ribbon的jar包。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMTA5NzQ2_size_16_color_FFFFFF_t_70

ribbon使用起来极其简单,用一个@LoadBalanced 注解就能实现基本的功能。在我们的RestTemplate Bean上增加注解,@LoadBalanced注解是属于Spring,而不是ribbon的,Spring在初始化容器的时候,如果检测到Bean被@LoadBalanced注解,Spring会为其设置LoadBalancerInterceptor的拦截器。

  1. package com.chen.config;
  2. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.client.RestTemplate;
  6. @Configuration
  7. public class ConsumerConfig {
  8. @Bean
  9. @LoadBalanced
  10. public RestTemplate restTemplate(){
  11. return new RestTemplate();
  12. }
  13. }

3、配置负载均衡接口

在controller里面新增一个接口,接口指定实例名和provider的接口名

  1. package com.chen.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.cloud.client.ServiceInstance;
  4. import org.springframework.cloud.client.discovery.DiscoveryClient;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import org.springframework.web.client.RestTemplate;
  9. import java.util.List;
  10. import java.util.concurrent.ThreadLocalRandom;
  11. @RestController
  12. @RequestMapping("/consumer")
  13. public class ConsumerController {
  14. @Autowired
  15. private DiscoveryClient discoveryClient;
  16. @Autowired
  17. private RestTemplate restTemplate;
  18. @GetMapping("/index")
  19. public String index(){
  20. List<ServiceInstance> provider = discoveryClient.getInstances("provider");
  21. int index = ThreadLocalRandom.current().nextInt(provider.size());
  22. String url = provider.get(index).getUri()+"/provider/index";
  23. return this.restTemplate.getForObject(url, String.class);
  24. }
  25. @GetMapping("/index_ribbon")
  26. public String index_ribbon(){
  27. return "ribbon均衡调用:"+this.restTemplate.getForObject("http://provider/provider/index", String.class);
  28. }
  29. }

OK,自此,调一下接口测试一下,浏览器输入:localhost:8080/consumer/index_ribbon

发现就是这两个接口进行轮询调用

20210817171142821.png

20210817171154170.png

ribbon如果不指定规则的话,那么就是默认轮询规则,按顺序依次调用。

4、设置随机规则

  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. # 配置nacos服务地址,如果不配置,默认是localhost:8848
  6. server-addr: localhost:8848
  7. application:
  8. name: consumer
  9. server:
  10. port: 8080
  11. provider:
  12. ribbon:
  13. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

我这里设置了com.netflix.loadbalancer.RandomRule随机规则,继续调接口测试可以发现,现在已经变成无规律的了。

5、设置权重规则

在nacos可视化界面,服务详情里面,可以看到每一个实例都可以单独设置权重

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMTA5NzQ2_size_16_color_FFFFFF_t_70 1

顾名思义,改变了这个权重值,那么在调接口的时候,就会根据这个权重去随机调取某个实例的接口,权重值越大, 调取接口的概率越大。但是,改完之后再进行测试可以发现,这个权重值没有生效,这还需要我们重写AbstractLoadBalancerRule类的choose方法进行实现,代码如下:

  1. package com.chen.config;
  2. import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
  3. import com.alibaba.cloud.nacos.ribbon.NacosServer;
  4. import com.alibaba.nacos.api.exception.NacosException;
  5. import com.alibaba.nacos.api.naming.NamingService;
  6. import com.alibaba.nacos.api.naming.pojo.Instance;
  7. import com.netflix.client.config.IClientConfig;
  8. import com.netflix.loadbalancer.AbstractLoadBalancerRule;
  9. import com.netflix.loadbalancer.BaseLoadBalancer;
  10. import com.netflix.loadbalancer.ILoadBalancer;
  11. import com.netflix.loadbalancer.Server;
  12. import lombok.extern.slf4j.Slf4j;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. @Slf4j
  15. public class NacosWeightedRule extends AbstractLoadBalancerRule {
  16. @Autowired
  17. private NacosDiscoveryProperties nacosDiscoveryProperties;
  18. @Override
  19. public void initWithNiwsConfig(IClientConfig iClientConfig) {
  20. //读取配置文件
  21. }
  22. @Override
  23. public Server choose(Object o) {
  24. ILoadBalancer loadBalancer = this.getLoadBalancer();
  25. BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) loadBalancer;
  26. //获取要请求的微服务名称
  27. String name = baseLoadBalancer.getName();
  28. //获取服务发现的相关API
  29. NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
  30. try {
  31. Instance instance = namingService.selectOneHealthyInstance(name);
  32. log.info("选择的实例是port={},instance={}",instance.getPort(),instance);
  33. return new NacosServer(instance);
  34. } catch (NacosException e) {
  35. e.printStackTrace();
  36. return null;
  37. }
  38. }
  39. }

然后,在yml文件里面把规则指向我们继承的这个规则类

  1. spring:
  2. cloud:
  3. nacos:
  4. discovery:
  5. # 配置nacos服务地址,如果不配置,默认是localhost:8848
  6. server-addr: localhost:8848
  7. application:
  8. name: consumer
  9. server:
  10. port: 8080
  11. provider:
  12. ribbon:
  13. NFLoadBalancerRuleClassName: com.chen.config.NacosWeightedRule

再次进行测试就会发现权重值已经生效。

发表评论

表情:
评论列表 (有 0 条评论,317人围观)

还没有评论,来说两句吧...

相关阅读