目录
- `Ribbon` 简介
- 服务器端负载均衡
- 客户端负载均衡
- 服务器端负载均衡 `VS` 客户端负载均衡
- `Ribbon` 实现客户端负载均衡
- 服务提供方 `Controller` 层
- 服务消费方引入依赖
- `Ribbon` 实现负载均衡
- 方式一
- 方式二
- `Ribbon` 负载均衡的策略
- `Ribbon` 的重试机制设置
- `Ribbon`工作流程
- 服务发现
- 服务选择
- 服务监听
Ribbon
简介
-
Ribbon
是Netflix
发布的开源项目,主要功能是提供客户端的软件负载均衡算法,是一个基于HTTP
和TCP
的客户端负载均衡工具 -
springCloud
对Ribbon
做了二次封装,可以让我们使用RestTemplate
的服务请求,自动转换成客户端负载均衡的服务调用 -
Ribbon
支持多种负载均衡算法,还支持自定义的负载均衡算法 -
Ribbon
只是一个工具类框架,比较小巧,springCloud
对它封装后使用也非常方便,它不像服务注册中心、配置中心、API
网关那样需要独立部署,Ribbon
只需要在代码直接使用即可
服务器端负载均衡
负载均衡是我们处理高并发、缓解网络压力和进行服务器扩容的重要手段之一,但是一般情况下我们所说的负载均衡通常都是指服务器端负载均衡,服务器端负载均衡又分为两种,一种是硬件负载均衡,还有一种是软件负载均衡
- 硬件负载均衡主要通过在服务器节点之前安装专门用于负载均衡的设备,常见的如:
F5
- 软件负载均衡则主要是在服务器上安装一些具有负载均衡功能的软件来完成请求分发进而实现负载均衡,常见的如:
LVS 、 Nginx 、Haproxy
无论是硬件负载均衡还是软件负载均衡,它的工作原理都不外乎下面这张图
客户端负载均衡
而微服务的出现,则为负载均衡的实现提供了另外一种思路:把负载均衡的功能以库的方式集成到服务的消费方,而不再是由一台指定的负载均衡设备集中提供。这种方案称为软负载均衡或者客户端负载均衡。常见的如:springCloud
中的 Ribbon
Ribbon
是一个基于 HTTP
和 TCP
的客户端负载均衡器,当我们将 Ribbon
和 Eureka
一起使用时,Ribbon
会到 Eureka
注册中心去获取服务端列表,然后进行轮询等方式访问以到达负载均衡的作用,客户端负载均衡也需要心跳机制去维护服务端清单的有效性,当然这个过程需要配合服务注册中心一起完成
在 springCloud
中,Ribbon
主要与 RestTemplate
对象配合起来使用,Ribbon
会自动化配置 RestTemplate
对象,通过 @LoadBalanced
开启 RestTemplate
对象调用时的负载均衡
服务器端负载均衡 VS
客户端负载均衡
- 服务器端负载均衡:客户端先发送请求到负载均衡服务器,然后由负载均衡服务器通过负载均衡算法,在众多可用的服务器之中选择一个来处理请求
- 客户端负载均衡:客户端自己维护一个可用服务器地址列表,在发送请求前先通过负载均衡算法选择一个将用来处理本次请求的服务器,然后再直接将请求发送至该服务器
Ribbon
实现客户端负载均衡
服务提供方 Controller
层
@RestController
@RequestMapping("/api/v1/msg")
public class MessageController {
@Value("${server.port}")
private String port;
@GetMapping("/get")
public String getMsg() {
return "This message is sent from port: " + port;
}
}
服务消费方引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
Ribbon
实现负载均衡
在启动类中向 spring
容器中注入一个带有 @LoadBalanced
注解的 RestTemplate
的 bean
@SpringBootApplication
@EnableEurekaClient
public class MessageCenterApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MessageCenterApplication.class, args);
}
}
方式一
@RestController
@RequestMapping("/api/v1/center")
public class MessageCenterController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/msg/get")
public Object getMsg() {
String msg = restTemplate.getForObject("http://message-service/api/v1/msg/get", String.class);
return msg;
}
}
方式二
直接使用 LoadBalancerClient
中的负载均衡策略获取一个可用的服务地址,然后再进行请求
@RestController
@RequestMapping("/api/v1/center")
public class MessageCenterController {
@Autowired
private LoadBalancerClient loadBalancer;
@GetMapping("/msg/get")
public Object getMsg() {
ServiceInstance instance = loadBalancer.choose("message-service");
URI url = URI.create(String.format("http://%s:%s/api/v1/msg/get", instance.getHost(), instance.getPort()));
String msg = restTemplate.getForObject(url, String.class);
return msg;
}
}
待应用启动之后,连续三次请求地址 http://localhost:8781/api/v1/center/msg/get
,返回的结果如图所示
Ribbon
负载均衡的策略
策略类 | 命名 | 描述 |
RandomRule | 随机策略 | 随机选择 server |
|
|
|
RetryRule | 重试策略 | 在一个配置时间段内,当选择 server 不成功,则一直尝试选择一个可用的 server |
BestAvailableRule | 最低并发策略 | 逐个考察 server,如果 server 断路器打开,则忽略,再选择其中并发链接最低的 server |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉一直失败并被标记为 circuit tripped 的 server,过滤掉那些高并发链接的 server(active connections 超过配置的阈值) |
ResponseTimeWeightedRule | 响应时间加权重策略 | 根据 server 的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io 等,都直接影响响应时间 |
ZoneAvoidanceRule | 区域权重策略 | 综合判断 server 所在区域的性能,和 server 的可用性,轮询选择 server 并且判断一个 AWS Zone 的运行性能是否可用,剔除不可用的 Zone 中的所有 server |
Ribbon
的重试机制设置
ribbon
实现了负载均衡,如果访问某服务的 A
节点超时后,会触发 ribbon
的重试机制
全局设置
ribbon:
ReadTimeout: 6000
ConnectTimeout: 6000
OkToRetryOnAllOperations: true
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
局部服务设置
service-id: # 服务ID
ribbon:
ConnectTimeout: 6000 # 毫秒 连接超时时间
ReadTimeout: 6000 # 毫秒 逻辑处理超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetries: 1 # 对当前实例的最大重试次数(请求服务超时6s则会再请求一次)
MaxAutoRetriesNextServer: 1 # 切换实例的最大重试次数(如果还失败就切换下个实例访问,切换一次)
Ribbon
工作流程
ribbon
与 eureka
配合使用的大致架构如下
服务发现
用于获取地址列表:当我们将 Ribbon
和 Eureka
一起使用时,Ribbon
会到 Eureka
注册中心去获取服务端服务实例列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)
服务选择
服务选择规则:根据用户指定的策略,再从它的实例列表选择一个列表地址。其中 Ribbon
提供了很多策略,例如轮询,随机 ,根据响应时间加权等。得到一个具体的服务列表地址后,再通过Feign
完成服务的调用
服务监听
也就是随时剔除无效的服务实例