【Ribbon】必知必会使用

549 阅读4分钟

这是我参与更文挑战的第11天,活动详情查看:更文挑战

一、前言

主流的负载方案分为两种:

  1. 集中式负载均衡:在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的负载均衡器,比如 F5,也有软件,比如 Nginx

    如图:

2020-11-3014-39-47.png

  1. 客户端负载均衡:客户端根据自己的请求情况做负载,Ribbon 就属于客户端自己做负载的框架。

    如图:

2020-11-3014-42-38.png


集中式负载均衡和客户端负载均衡最大的区别:

**对服务实例信息的维护。**集中式负载均衡的信息是集中进行维护的,比如 Nginx,都会在配置文件中进行指定。

客户端负载均衡的信息是在客户端本地进行维护的,我们可以手动配置,但最常见的是从注册中心进行定时拉取。


Ribbon 属于第二种:

Ribbon是一个经过云端测试的IPC库,可以很好地控制HTTPTCP客户端的负载均衡行为。

Ribbon 配置服务提供者地址后,Ribbon 就可基于某种负载均衡算法,自动的帮助服务消费者进行请求。同时 Ribbon 默认为我们提供了很多负载均衡算法,例如:轮询、随机算法等。


Fegin默认集成了Ribbon

Ribbon子模块如下:

  • ribbon-loadbalancer:可以独立使用或与其他模块一起使用的负载均衡器 API
  • ribbon-eurekaRibbon结合 Eureka客户端的 API,为负载均衡器提供动态服务注册列表信息
  • ribbon-coreRibbon的核心 API


二、Ribbon 主要组件

脑图如下:

2020-11-3014-45-45.png

各组件作用如下:

组件作用
LoadBalancer定义了一系列的操作接口,比如选择服务实例。
IRule算法策略,内置了很多的算法策略来为服务实例的选择提供服务。
ServerList负责服务实例信息的获取,可以获取配置文件中的,也可以从注册中心获取。
ServerListFilter可以过滤掉某些不想要的服务实例信息。
ServerListUpdater负责更新本地缓存的服务实例信息。
IPing对已有的服务实例进行可用性检查,保证选择到的服务都是可用的。

在这个选择服务实例的过程中,服务实例信息是怎么来的呢?

如图:

2020-11-3014-46-41.png

  1. 存储组件

    这就需要一个服务实例的存储组件来支持,ServerList 就是这个组件。存储分为静态动态两种方式。

    静态存储需要事先配置好固定的服务实例信息,动态存储需要从注册中心获取对应的服务实例信息。

  2. 过滤组件

    有了服务信息后,在某些场景下可能需要过滤一部分信息,这个时候可以用 ServerListFilter 组件来实现过滤操作。

  3. 更新组件

    Ribbon 会将服务实例在本地内存中存储一份,这样就不需要每次都去注册中心获取信息,这种场景的问题在于当服务实例增加或者减少后,本地怎么更新呢?

    这个时候就需要用到 ServerListUpdater 组件,ServerListUpdater 组件就是用于服务实例更新操作。

  4. 是否可用

    还有个问题就是,缓存到本地的服务实例信息有可能已经无法提供服务了,这个时候就需要有一个检测的组件,来检测服务实例信息是否可用,这个组件就是 IPing

  5. 选择

    Ribbon 会根据指定的算法来选择一个可用的实例信息,IRule 组件提供了很多种算法策略来选择实例信息。

最后就是使用的入口了,要选择一个可用的服务,怎么选择?问谁要这个服务?

这时 ILoadBalancer 就上场了,ILoadBalancer 中定义了软件负载均衡操作的接口,比如动态更新一组服务列表,根据指定算法从现有服务器列表中选择一个可用的服务等操作。



三、简单使用

主要应用SpringCloud

Ribbon 的使用方式主要分为下面这三种:

  1. 原生 APIRibbonNetflix 开源的,如果你没有使用 Spring Cloud,也可以在项目中单独使用 Ribbon,在这种场景下就需要使用 Ribbon 的原生 API

  2. Ribbon + RestTemplate,当项目整合了 Spring Cloud 时,就可以用 RibbonRestTemplate 提供负载均衡的服务。

  3. Ribbon + Feign

(1)原生 API 使用

ILoadBalancer balancer = new BaseLoadBalancer(); 

List<Server> servers = new ArrayList<Server>();
servers.add(new Server("localhost", 8080));
servers.add(new Server("localhost", 8088));

balancer.addServers(servers); 
for(int i = 0; i < 10; i++) {
    Server server = balancer.chooseServer(null);
    System.out.println(server);
} 

(2)Ribbon + RestTemplate

简单介绍下,实现原理:

  • 通过在 RestTemplate 上增加 @LoadBalanced 添加拦截器
  • 拦截器中通过 Ribbon 选取服务实例
  • 然后将请求地址中的服务名称替换成 Ribbon 选取服务实例的 IP 和 端口
  1. pom.xml 配置文件
        <!-- `SpringCloud`中`eureka-client` -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <!-- 直接导入`ribbon` -->
        <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>
  1. RestTemplate中使用
@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {

        return new RestTemplate();
    }
}