概述
官方github:https://github.com/Netflix/ribbon
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.
Ribbon is a client side IPC library that is battle-tested in cloud. It provides the following features Load balancing Fault tolerance Multiple protocol (HTTP, TCP, UDP) support in an asynchronous and reactive model Caching and batching Ribbon 是一个进程间通信的客户端库,并且已经在云环境下经过大量的生产测试。它提供了以下功能: 负载均衡 容错机制 支持 HTTP、TCP、UDP 等多种协议,并支持异步和响应式的调用方式 缓存与批处理
mavn配置
<dependency><groupId>com.netflix.ribbon</groupId><artifactId>ribbon</artifactId><version>2.2.2</version></dependency>
Ribbon的常用配置
全局配置
ribbon:ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)ReadTimeout: 3000 #服务请求处理超时时间(毫秒)OkToRetryOnAllOperations: true #对超时请求启用重试机制MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数MaxAutoRetries: 1 # 切换实例后重试最大次数NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
指定服务进行配置
与全局配置的区别就是ribbon节点挂在服务名称下面,如下是对ribbon-service调用user-service服务时的单独配置。
user-service:ribbon:ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)ReadTimeout: 3000 #服务请求处理超时时间(毫秒)OkToRetryOnAllOperations: true #对超时请求启用重试机制MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数MaxAutoRetries: 1 # 切换实例后重试最大次数NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #修改负载均衡算法
负载均衡策略
负载均衡策略就是指当A服务调用B服务时,此时B服务有多个实例,这时A服务以何种方式来选择调用的B实例,ribbon可以选择以下几种负载均衡策略。
| 负载均衡策略 | 说明 |
|---|---|
| com.netflix.loadbalancer.RandomRule | 从提供服务的实例中以随机的方式 |
| com.netflix.loadbalancer.RoundRobinRule | 以线性轮询的方式,就是维护一个计数器,从提供服务的实例中按顺序选取,第一次选第一个,第二次选第二个,以此类推,到最后一个以后再从头来过 |
| com.netflix.loadbalancer.RetryRule | 在RoundRobinRule的基础上添加重试机制,即在指定的重试时间内,反复使用线性轮询策略来选择可用实例 |
| com.netflix.loadbalancer.WeightedResponseTimeRule | 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择 |
| com.netflix.loadbalancer.BestAvailableRule | 选择并发较小的实例 |
| com.netflix.loadbalancer.AvailabilityFilteringRule | 先过滤掉故障实例,再选择并发较小的实例 |
| com.netflix.loadbalancer.ZoneAwareLoadBalancer | 采用双重过滤,同时过滤不是同一区域的实例和故障实例,选择并发较小的实例 |
| 策略名 | 策略描述 | 实现说明 |
|---|---|---|
| RandomRule | 随机选择一个 server | 在 index 上随机,选择 index 对应位置的 Server |
| RoundRobinRule | 轮询选择 server | 轮询 index,选择 index 对应位置的 server |
| ZoneAvoidanceRule | 复合判断 server 所在区域的性能和 server 的可用性选择 server | 使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 server。ZoneAvoidancePredicate 判断判定一个 zone 的运行性能是否可用,剔除不可用的 zone(的所有 server);AvailabilityPredicate 用于过滤掉连接数过多的 server。 |
| BestAvailableRule | 选择一个最小并发请求的 server | 逐个考察 server,如果 server 被 tripped 了则忽略,在选择其中activeRequestsCount 最小的 server |
| AvailabilityFilteringRule | 过滤掉那些因为一直连接失败的被标记为 circuit tripped 的后端 server,并过滤掉那些高并发的的后端 server(activeConnections 超过配置的阈值) | 使用一个 AvailabilityPredicate 来包含过滤 server 的逻辑,其实就就是检查 status 里记录的各个 server 的运行状态 |
| WeightedResponseTimeRule | 根据 server 的响应时间分配一个 weight,响应时间越长,weight 越小,被选中的可能性越低 | 一个后台线程定期的从 status 里面读取评价响应时间,为每个 server 计算一个 weight。weight 的计算也比较简单,responseTime 减去每个 server 自己平均的 responseTime 是 server 的权重。当刚开始运行,没有形成 status 时,使用 RoundRobinRule 策略选择 server。 |
| RetryRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择 server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 server |
默认情况下,Ribbon 采用 ZoneAvoidanceRule 规则。因为大多数公司是单机房,所以一般只有一个 zone,而 ZoneAvoidanceRule 在仅有一个 zone 的情况下,会退化成轮询的选择方式,所以会和 RoundRobinRule 规则类似。
创建user-service

在pom.xml 添加相关依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
application.yaml 配置文件
server:port: 8201spring:application:name: user-serviceeureka:client:register-with-eureka: truefetch-registry: trueservice-url:defaultZone: http://localhost:8001/eureka/
创建
一个服务启动多个实例
查看eureka注册中心

调用接口进行测试:http://localhost:8301/user/1
使用nacos
<dependencies><!-- 引入 SpringMVC 相关依赖,并实现对其的自动配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 引入 Spring Cloud Alibaba Nacos Discovery 相关依赖,将 Nacos 作为注册中心,并实现对其的自动配置 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies>
没有主动引入 spring-cloud-netflix-ribbon 依赖,因为 spring-cloud-starter-alibaba-nacos-discovery 默认引入了它
application.yaml
server:port: 18808spring:application:name: ribbon-echo-provider # 应用名cloud:nacos:# Nacos 作为注册中心的配置项,对应 NacosDiscoveryProperties 配置类discovery:server-addr: 127.0.0.1:8848 # Nacos 服务器地址
创建RibbonEchoController
@RestControllerpublic class RibbonEchoController {@Value("${server.port}")private Integer serverPort;@GetMapping("/echo")public String echo(String s) throws InterruptedException {// 模拟执行 100ms 时长。方便后续我们测试请求超时Thread.sleep(100L);return serverPort+" [echo]:" + s;}}
http://127.0.0.1:18808/echo?s=hello
消费者
@LoadBalanced 注解,声明 RestTemplate Bean 被配置使用 Spring Cloud LoadBalancerClient(负载均衡客户端),实现在请求目标服务时,能够进行负载均衡。
@Configurationpublic class RestTemplateConfig {@Bean(name = "restTemplate")public RestTemplate restTemplate(){return new RestTemplate();}@Bean(name = "loadBalancedRestTemplate")@LoadBalancedpublic RestTemplate loadBalancedRestTemplate(){return new RestTemplate();}}@Configurationpublic class RestTemplateConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}}
消费端配置信息application.yaml
server:port: 18080 # 服务器端口。默认为 8080spring:application:name: ribbon-echo-consumer # Spring 应用名cloud:nacos:# Nacos 作为注册中心的配置项,对应 NacosDiscoveryProperties 配置类discovery:server-addr: 127.0.0.1:8848 # Nacos 服务器地址service-url:ribbon-echo-service: ribbon-echo-provider
controller
@RestControllerpublic class EchoLoadBalancerController {@Value("${service-url.ribbon-echo-service}")private String ribbonEchoServer;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate RestTemplate loadBalancedRestTemplate;@Autowiredprivate LoadBalancerClient loadBalancerClient;@GetMapping("/client")public String client(String str) {// 获得服务 `ribbonEchoServer` 的一个实例ServiceInstance instance = loadBalancerClient.choose(ribbonEchoServer);if (instance!=null){// 发起调用String targetUrl = instance.getUri() + "/echo?s=" + str;String response = restTemplate.getForObject(targetUrl, String.class);// 返回结果return "client:" + response;}return "client";}@GetMapping("/temp")public String temp(String str) {String targetUrl = "http://"+ribbonEchoServer+"/echo?s=" + str;String response = loadBalancedRestTemplate.getForObject(targetUrl, String.class);// 返回结果return "temp:" + response;}}
/client 接口,使用 LoadBalancerClient 先选择服务 ribbon-echo-provider 的一个实例,在使用 RestTemplate 调用服务ribbon-echo-provider的 /echo 接口。不过要注意,这里执行会报如下异常:
ava.lang.IllegalStateException: No instances available for 192.168.0.107at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:119) ~[spring-cloud-netflix-ribbon-2.2.6.RELEASE.jar:2.2.6.RELEASE]
- 因为我们这里创建的 RestTemplate Bean 是添加了 @LoadBalanced 注解,它会把传入的 “192.168.0.107” 当做一个服务,显然是找不到对应的服务实例,所以会报 IllegalStateException 异常。
- 解决办法也非常简单,再声明一个未使用 @LoadBalanced 注解的 RestTemplate Bean 即可,并使用它发起请求。
查看nacos服务
测试
http://localhost:18080/client?str=test
http://localhost:18080/temp?str=test
