负载均衡-Ribbon

一. Ribbon概述

Spring Cloud Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon客户端组件提 供一系列的完善的配置,如超时,重试等。通过Load Balancer获取到服务提供的所有机器实例, Ribbon会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。

二. 主流负载均衡

  • 集中式负载均衡

在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。

  • 客户端负载均衡

客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择 一个服务器,然后进行访问,这是客户端负载均衡。

三. 常见负载均衡算法

算法就是从服务列表中按某个规则选取一个。

  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;

  • 轮训,负载均衡默认实现方式,请求来之后排队处理;

  • 加权轮训,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个 服务器的压力;

  • 地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度。

  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上。

服务每处理一个请求,请求数+1,处理完-1. 新的请求来时选择请求数最少的处理。这样性能最好的服务器接收最多的请求。

四. Ribbon 模块

  • ribbon- loadbalancer

负载均衡模块,可独立使用,也可以和别的模块一起使用。 Ribbon 内置的负载均衡算法都实现在其中。

  • ribbon-eureka

基于 Eureka 封装的模块,能够快速、方便地集成 Eureka。

  • ribbon-transport

基于 Netty 实现多协议的支持,比如 HTTP、Tcp、Udp 等。

  • ribbon-httpclient

基于 Apache HttpClient 封装的 REST 客户端,集成了负载均衡模块,可以直接在项目中使用来调用接口。

  • ribbon-example

Ribbon 使用代码示例,通过这些示例能够让你的学习事半功倍。

  • ribbon-core

一些比较核心且具有通用性的代码,客户端 API 的一些配置和其他 API 的定义。

五. Ribbon 使用

5.1 直接使用

 // 服务列表
        List<Server> serverList = Lists.newArrayList(
                new Server("localhost", 8020),
                new Server("localhost", 8021));
        // 构建负载实例
        ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
                .buildFixedServerListLoadBalancer(serverList);
        // 调用 5 次来测试效果
        for (int i = 0; i < 5; i++) {
            String result = LoadBalancerCommand.<String>builder()
                    .withLoadBalancer(loadBalancer).build()
                    .submit(new ServerOperation<String>() {
                        @Override
                        public Observable<String> call(Server server) {
                            String addr = "http://" + server.getHost() + ":" +
                                    server.getPort() + "/order/findOrderByUserId/1";
                                System.out.println(" 调用地址:" + addr);
                            URL url = null;
                            try {
                                url = new URL(addr);
                                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                conn.setRequestMethod("GET");
                                conn.connect();
                                InputStream in = conn.getInputStream();
                                byte[] data = new byte[in.available()];
                                in.read(data);
                                return Observable.just(new String(data));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            return null;
                        }
                    }).toBlocking().first();

            System.out.println(" 调用结果:" + result);
        }
    }

5.2 Spring Cloud快速整合Ribbon

<!‐‐添加ribbon的依赖‐‐> 
 <dependency> 
        <groupId>org.springframework.cloud</groupId> 
        <artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId> 
 </dependency>

@Configuration 
public class RestConfig { 
     @Bean 
     @LoadBalanced
     public RestTemplate restTemplate() { 
           return new RestTemplate(); 
     } 
}
@Autowired 
private RestTemplate  restTemplate;  

@RequestMapping(value = "/findOrderByUserId/{id}") 
public R findOrderByUserId(@PathVariable("id") Integer id) { 
      
    String url = "http://mall‐order/order/findOrderByUserId/"+id;
    R result = restTemplate.getForObject(url,R.class);  
    return result; 
}

六. Ribbon原理

Ribbon 本质上是基于RestTemplate 的扩展点,拦截原本请求后,利用负载均衡算法在服务列表中选出一个服务,替换服务名实现负载均衡调用的。

Ribbon实现原理

@LoadBalanced 原理

1.LoadBalancerAutoConfiguration 自动注入

2.@LoadBalanced利用@Qualifier作为restTemplates注入的筛选条件,筛选出具有负载均衡标识的 RestTemplate。

  1. 被@LoadBalanced注解的restTemplate会被定制,添加LoadBalancerInterceptor拦截器。


    image.png

七. Ribbon 相关接口

源码入口RibbonClientConfiguration

  • IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现,该策略能够在多区域环境下选出 最佳区域的实例进行访问。
  • IPing:Ribbon的实例检查策略,默认采用DummyPing实现,该检查策略是一个特殊的实现,实际上 它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。
  • ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现。
  • ServerListFilter:服务实例清单过滤机制,默认采ZonePreferenceServerListFilter,该策略能够优先 过滤出与请求方处于同区域的服务实例。
  • ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现,它具备了区域感知的能力。

八. Ribbon负载均衡策略

即IRule的实现


IRule实现
  1. RandomRule: 随机选择一个Server。
  2. RetryRule: 对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server。
  3. RoundRobinRule: 轮询选择, 轮询index,选择index对应位置的Server。
  4. AvailabilityFilteringRule: 过滤掉一直连接失败的被标记为circuit tripped的后端Server,并 过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其 实就是检查status里记录的各个Server的运行状态。
  5. BestAvailableRule: 选择一个最小的并发请求的Server,逐个考察Server,如果Server被 tripped了,则跳过。
  6. WeightedResponseTimeRule: 根据响应时间加权,响应时间越长,权重越小,被选中的可 能性越低。
  7. ZoneAvoidanceRule: 默认的负载均衡策略,即复合判断Server所在区域的性能和 Server的可用性选择Server,在没有区域的环境下,类似于轮询(RandomRule)
  8. NacosRule: 同集群优先调用

九.自定义负载均衡策略

自定义

public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
      @Override 
      public Server choose(Object key) {
            .... .... ....
            return Server
      }
}

全局生效

@Configuration 
public class RibbonConfig { 
       /** 
         * 全局配置 
         * 指定负载均衡策略 
         * @return 
         */ 
  @Bean 
  public IRule() { 
       // 
       return new  NacosRandomWithWeightRule(); 
  } 
}

局部生效

//修改application.yml
# 被调用的微服务名 
   mall‐order: 
           ribbon: 
                 # 指定使用负载均衡策略 
                     NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule

十. 饥饿加载

开启饥饿加载,解决第一次调用慢的问题

 ribbon:
         eager‐load: 
                 # 开启ribbon饥饿加载 
                 enabled: true 
                 # 配置mall‐user使用ribbon饥饿加载,多个使用逗号分隔 
                 clients: mall‐order
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容