一、什么是Ribbon
Ribbon为Netflix发布的一款客户端负载均衡器。在SpringCloud中Eureka一般配合Ribbon使用,Ribbon利用从Rureka中获取到服务提供者列表信息,并基于内置的负载均衡算法进行选择调用。Ribbon的底层也是对RestTemplate进行封装,使用http请求进行调用。
二、Ribbon的作用有哪些
1,服务调用
Ribbon 的服务调动为通过注册中心获取服务列表组成(服务名-请求路径)映射关系。并借助RestTemplate对象完成服务调用
2,客户端负载均衡
负载均衡在端类型上分为服务端负载均衡和客户端负载均衡,有点类似正向代理(客户端)和反向代理(服务端)。按软硬件分为软件负载均衡和硬件负载均衡。我们常见的Nginx、lvs为服务端负载均衡软件,F5为服务端负载均衡硬件。Ribbon为客户端负载均衡软件。
Ribbon的负载均衡测试包含:
- 轮询方式策略(com.netflix.loadbalancer.RoundRobinRule)
- 随机策略(com.netflix.loadbalancer.RandomRule)
- 重试策略(com.netflix.loadbalancer.RetryRule)
- 权重策略(com.netflix.loadbalancer.WeightedResponseTimeRule 会计算每个服务的权重,越高的调用次数越大)
- 最佳策略(com.netflix.loadbalancer.BestAvailableRule 遍历所有服务实例,并过滤掉故障实例,并返回请求数最小的实例,类似dubbo的最小活跃数策略)
- 可用过滤策略(com.netflix.loadbalancer.AvailabilityFilteringRule 过滤掉故障和请求数超过阈值的服务实例,再从剩下的实例中轮询调用)
3,使用Ribbon的请求重试功能
通过添加spring.retry依赖 和结合Ribbon的配置可以实现Ribbon的请求重试功能。
三、Ribbon的配置使用
1,服务调用代码
为RestTemplate bean对象添加@org.springframework.cloud.client.loadbalancer.LoadBalanced 注解(Eureka 依赖已经引入不需要在添加依赖);在使用RestTemplate对象调用远程接口时,可以将接口地址中的ip和端口部分可以使用注册中心中的服务ID代替;
参考消费者工程中的RestTemplate配置类代码如下(重点):
package com.xiaohui.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
*
* 相当于 spring的 application.xml bean注解相当于 bean 标签
*/
@Configuration
public class ApplicationContextConfig {
@LoadBalanced
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
使用restTemplate 的Controller 代码如下,其中第三种调用方式中 在接口地址中直接使用了服务提供者的工程的服务名:
package com.xiaohui.springcloud.controller;
import com.xiaohui.springcloud.entities.CommonResult;
import com.xiaohui.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class OrderController {
public static String PAYMENT_URL = "http://127.0.0.1:8001";
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
@GetMapping("/consumer/payment/get2/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
ServiceInstance serviceInstance = instances.get(0);
return restTemplate.getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/payment/get/"+id,CommonResult.class);
}
@GetMapping("/consumer/payment/get3/{id}")
public CommonResult<Payment> getPayment3(@PathVariable("id") Long id){
CommonResult<Payment> commonResult = null;
commonResult = restTemplate.getForObject("http://cloud-payment-service/payment/get/"+id,CommonResult.class);
return commonResult;
}
}
2,负载均衡配置实现:
轮询策略:在上面的使用Ribbon的调用配置后,Ribbon会使用默认的负载均衡测试进行调用,即轮询策略,当该服务又多个服务提供者节点时,Ribbon会逐一轮询调用每个节点。测试方式:我们启动两个不同端口的服务提供者节点,端口分别为8001,和8002。在节点处理返回结果时添加上当前提供者节点的ip和端口信息来观察请求路由到哪一个节点上,观察调用效果:注意负载均衡策略配置在消费者节点配置中,因为Ribbon为客户端负载均衡器
- 默认轮询策略
默认的负载均衡实现类为:com.netflix.loadbalancer.RoundRobinRule。我们在服务端返回处理调用的当前服务接口ip端口,效果如下可以看到端口8002、8001 进行顺序切换。
- 随机策略:
如果需要修改默认的轮询负载均衡算法,则可以在客户端配置文件上对cloud-payment-service.ribbon.NFLoadBalancerRuleClassName 键值进行修改,如下配置将默认的负载均衡算法实现修改为随机算法:(cloud-payment-service 为服务端的服务名称)
cloud-payment-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
和上面的环境一样我们开启两个生产者服务,然后返回处理请求的服务节点ip和端口信息,通过返回可以看出 处理节点在 8002、8001 上随机进行请求。
- 重试配置:通过引入spring.retry 可以实现服务的容错能力。当某一个节点在处理请求超时,则可以根据超时重试配置规则进行换一台服务节点进行重新请求。如 如下配置,当服务节点和连接节点后的数据处理时间超过对应配置的时间后没有相应则会进行切换节点进行重新发起请求。MaxAutoRetriesNextServer 表示重新请求的最大次数。MaxAutoRetries表示对当前故障节点的再次重启次数。
maven 添加依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
application.yml 文件添加配置如下
cloud-payment-service:
ribbon:
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ConnectTimeout: 250 #Ribbon的 链接超时时间
ReadTimeout: 1000 #Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true #是否对所有操作都重试
MaxAutoRetriesNextServer: 1 #切换实例的重试次数
MaxAutoRetries: 1 #对当前实例的重试次数