原创

微服务SpringCloud之Ribbon负载均衡器

Ribbon简介
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,如轮询、随机等。
在SpringCloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,基于负载均衡算法、请求其中某一个提供者实例。
Ribbon 中的核心概念

  • Rule — 这个组件决定了从一堆候选服务器中返回那个服务器地址进行远程调用的操作。
  • Ping — 在后台运行的组件,确认哪些服务器是存活可用的。
  • ServerList — 当前可以用作 LB 的服务器列表,这个列表可以是静态的,也可以是动态的。如果是动态列表(例如从 Eurka 服务器获取),则会有一个后台线程按照时间间隔刷新列表。
    Ribbon 提供了 3 中 Rule供我们使用
  • RoundRobinRule: 最简单的规则,会在 ServerList 中依次调用。
  • AvailabilityFilteringRule: 在这种规则下 Ribbon 集成了 Hystrix 的功能,默认情况下调用某个远程方法失败 3 次后,断路器的开关会被打开,而之后的请求中 Ribbon 会跳过这个服务器地址,直到 30 秒之后断路器关闭后才会重新加入调用列表。
  • WeightedResponseTimeRule: 将响应时间作为权重的负载规则,当某个服务器的响应时间越长,则它的权重就越低。具体选择服务器时,结合权重进行随机选择。
    LB方案分类
    目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于后者,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
    Ribbon负载策略
  • 简单轮询负载均衡(RoundRobin):以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。
  • 随机负载均衡 (Random): 随机选择状态为UP的Server。
  • 加权响应时间负载均衡 (WeightedResponseTime):根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。
  • 区域感知轮询负载均衡(ZoneAvoidanceRule):复合判断server所在区域的性能和server的可用性选择server
    Ribbon自带负载均衡策略比较。
    结合Eureka使用Ribbon
    依赖


    org.springframework.cloud
    spring-cloud-starter-ribbon


    org.springframework.cloud
    spring-cloud-starter-eureka

    在应用主类中,通过@EnableDiscoveryClient注解来添加发现服务能力。创建RestTemplate实例,并通过@LoadBalanced注解开启均衡负载能力。
    /**

     @author :邬志斌(www.wzbjsz.cn)
     @date :Created in 2019 06 15
    

    */

    @SpringBootApplication
    @EnableDiscoveryClient
    public class RibbonApplication {

     @Bean
     @LoadBalanced
     RestTemplate restTemplate() {
         return new RestTemplate();
     }
     public static void main(String[] args) {
         SpringApplication.run(RibbonApplication.class, args);
     }
    

    }
    创建ConsumerController来消费service01的getuser服务。通过直接RestTemplate来调用服务
    /**

     @author :邬志斌(www.wzbjsz.cn)
     @date :Created in 2019 06 15
    

    */

    @RestController
    public class ConsumerController {

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/getuserinfo", method = RequestMethod.GET)
    public String add() {

     return restTemplate.getForEntity("http://biz-service-0/getuser", String.class).getBody();
    

    }
    }
    我在项目中使用Ribbon的场景是不使用Feignclient 进行服务与服务直接调用,而是用到httpclient,如果自己使用ip+端口在内部网络是可以的,如果放到云服务上这种实现是不合理的,我采用Feignclient的原理使用Httpclient+Eureka client + Ribbon 进行服务直接内部调用,研究过Feignclient的就知道这种操作,就是利用Ribbon基于负载均衡算法获取指定服务的地址(可能是docker地址)。如果不使用Ribbon获取地址,直接使用Eureka client 获取,如果是多个节点可能会是多个地址,自己做的负载均衡在单个线程中是可以满足的,实现起来也比较麻烦,不如直接使用Riboon 快捷方便。
    ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer("[服务名]");
    饥饿加载
    SpringCloud会为每个名称的RibbonClient维护一个子应用程序上下文,这个上下文默认是懒加载,指定名称的Ribbonclient第一次请求时,对应的上下文才会被加载,因此,首次请求往往会比较慢。从SpringCloud Dalston开始,就可以配置饥饿加载了:
    ribbon:
    eager-load:

     enabled: true
     clients: client1,client2
    

    对于clent1,client2的Ribbonclient,将在启动时就加载对应的子应用程序上下文,从而提高首次请求的访问速度。

正文到此结束
本文目录