这是我参与更文挑战的第11天,活动详情查看:更文挑战
一、前言
主流的负载方案分为两种:
-
集中式负载均衡:在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的负载均衡器,比如
F5,也有软件,比如Nginx。如图:
-
客户端负载均衡:客户端根据自己的请求情况做负载,
Ribbon就属于客户端自己做负载的框架。如图:
集中式负载均衡和客户端负载均衡最大的区别:
**对服务实例信息的维护。**集中式负载均衡的信息是集中进行维护的,比如
Nginx,都会在配置文件中进行指定。客户端负载均衡的信息是在客户端本地进行维护的,我们可以手动配置,但最常见的是从注册中心进行定时拉取。
Ribbon 属于第二种:
Ribbon是一个经过云端测试的IPC库,可以很好地控制HTTP和TCP客户端的负载均衡行为。
为
Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动的帮助服务消费者进行请求。同时Ribbon默认为我们提供了很多负载均衡算法,例如:轮询、随机算法等。
Fegin默认集成了Ribbon
Ribbon子模块如下:
ribbon-loadbalancer:可以独立使用或与其他模块一起使用的负载均衡器APIribbon-eureka:Ribbon结合Eureka客户端的API,为负载均衡器提供动态服务注册列表信息ribbon-core:Ribbon的核心API
二、Ribbon 主要组件
脑图如下:
各组件作用如下:
| 组件 | 作用 |
|---|---|
LoadBalancer | 定义了一系列的操作接口,比如选择服务实例。 |
IRule | 算法策略,内置了很多的算法策略来为服务实例的选择提供服务。 |
ServerList | 负责服务实例信息的获取,可以获取配置文件中的,也可以从注册中心获取。 |
ServerListFilter | 可以过滤掉某些不想要的服务实例信息。 |
ServerListUpdater | 负责更新本地缓存的服务实例信息。 |
IPing | 对已有的服务实例进行可用性检查,保证选择到的服务都是可用的。 |
在这个选择服务实例的过程中,服务实例信息是怎么来的呢?
如图:
-
存储组件
这就需要一个服务实例的存储组件来支持,
ServerList就是这个组件。存储分为静态和动态两种方式。静态存储需要事先配置好固定的服务实例信息,动态存储需要从注册中心获取对应的服务实例信息。
-
过滤组件
有了服务信息后,在某些场景下可能需要过滤一部分信息,这个时候可以用
ServerListFilter组件来实现过滤操作。 -
更新组件
Ribbon会将服务实例在本地内存中存储一份,这样就不需要每次都去注册中心获取信息,这种场景的问题在于当服务实例增加或者减少后,本地怎么更新呢?这个时候就需要用到
ServerListUpdater组件,ServerListUpdater组件就是用于服务实例更新操作。 -
是否可用
还有个问题就是,缓存到本地的服务实例信息有可能已经无法提供服务了,这个时候就需要有一个检测的组件,来检测服务实例信息是否可用,这个组件就是
IPing。 -
选择
Ribbon会根据指定的算法来选择一个可用的实例信息,IRule组件提供了很多种算法策略来选择实例信息。
最后就是使用的入口了,要选择一个可用的服务,怎么选择?问谁要这个服务?
这时
ILoadBalancer就上场了,ILoadBalancer中定义了软件负载均衡操作的接口,比如动态更新一组服务列表,根据指定算法从现有服务器列表中选择一个可用的服务等操作。
三、简单使用
主要应用
SpringCloud
Ribbon 的使用方式主要分为下面这三种:
-
原生
API,Ribbon是Netflix开源的,如果你没有使用Spring Cloud,也可以在项目中单独使用Ribbon,在这种场景下就需要使用Ribbon的原生API。 -
Ribbon + RestTemplate,当项目整合了Spring Cloud时,就可以用Ribbon为RestTemplate提供负载均衡的服务。 -
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和 端口
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>
RestTemplate中使用
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}