这是我参与更文挑战的第11天,活动详情查看:更文挑战
一、前言
主流的负载方案分为两种:
-
集中式负载均衡:在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的负载均衡器,比如
F5
,也有软件,比如Nginx
。如图:
-
客户端负载均衡:客户端根据自己的请求情况做负载,
Ribbon
就属于客户端自己做负载的框架。如图:
集中式负载均衡和客户端负载均衡最大的区别:
**对服务实例信息的维护。**集中式负载均衡的信息是集中进行维护的,比如
Nginx
,都会在配置文件中进行指定。客户端负载均衡的信息是在客户端本地进行维护的,我们可以手动配置,但最常见的是从注册中心进行定时拉取。
Ribbon
属于第二种:
Ribbon
是一个经过云端测试的IPC
库,可以很好地控制HTTP
和TCP
客户端的负载均衡行为。
为
Ribbon
配置服务提供者地址后,Ribbon
就可基于某种负载均衡算法,自动的帮助服务消费者进行请求。同时Ribbon
默认为我们提供了很多负载均衡算法,例如:轮询、随机算法等。
Fegin
默认集成了Ribbon
Ribbon
子模块如下:
ribbon-loadbalancer
:可以独立使用或与其他模块一起使用的负载均衡器API
ribbon-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();
}
}