一. Ribbon概述
Spring Cloud Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon客户端组件提 供一系列的完善的配置,如超时,重试等。通过Load Balancer获取到服务提供的所有机器实例, Ribbon会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。
二. 主流负载均衡
- 集中式负载均衡
在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx)。
- 客户端负载均衡
客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择 一个服务器,然后进行访问,这是客户端负载均衡。
三. 常见负载均衡算法
算法就是从服务列表中按某个规则选取一个。
随机,通过随机选择服务进行执行,一般这种方式使用较少;
轮训,负载均衡默认实现方式,请求来之后排队处理;
加权轮训,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个 服务器的压力;
地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度。
最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上。
服务每处理一个请求,请求数+1,处理完-1. 新的请求来时选择请求数最少的处理。这样性能最好的服务器接收最多的请求。
四. Ribbon 模块
- ribbon- loadbalancer
负载均衡模块,可独立使用,也可以和别的模块一起使用。 Ribbon 内置的负载均衡算法都实现在其中。
- ribbon-eureka
基于 Eureka 封装的模块,能够快速、方便地集成 Eureka。
- ribbon-transport
基于 Netty 实现多协议的支持,比如 HTTP、Tcp、Udp 等。
- ribbon-httpclient
基于 Apache HttpClient 封装的 REST 客户端,集成了负载均衡模块,可以直接在项目中使用来调用接口。
- ribbon-example
Ribbon 使用代码示例,通过这些示例能够让你的学习事半功倍。
- ribbon-core
一些比较核心且具有通用性的代码,客户端 API 的一些配置和其他 API 的定义。
五. Ribbon 使用
5.1 直接使用
// 服务列表
List<Server> serverList = Lists.newArrayList(
new Server("localhost", 8020),
new Server("localhost", 8021));
// 构建负载实例
ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
.buildFixedServerListLoadBalancer(serverList);
// 调用 5 次来测试效果
for (int i = 0; i < 5; i++) {
String result = LoadBalancerCommand.<String>builder()
.withLoadBalancer(loadBalancer).build()
.submit(new ServerOperation<String>() {
@Override
public Observable<String> call(Server server) {
String addr = "http://" + server.getHost() + ":" +
server.getPort() + "/order/findOrderByUserId/1";
System.out.println(" 调用地址:" + addr);
URL url = null;
try {
url = new URL(addr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
byte[] data = new byte[in.available()];
in.read(data);
return Observable.just(new String(data));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}).toBlocking().first();
System.out.println(" 调用结果:" + result);
}
}
5.2 Spring Cloud快速整合Ribbon
<!‐‐添加ribbon的依赖‐‐>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId>
</dependency>
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
String url = "http://mall‐order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);
return result;
}
六. Ribbon原理
Ribbon 本质上是基于RestTemplate 的扩展点,拦截原本请求后,利用负载均衡算法在服务列表中选出一个服务,替换服务名实现负载均衡调用的。

@LoadBalanced 原理
1.LoadBalancerAutoConfiguration 自动注入
2.@LoadBalanced利用@Qualifier作为restTemplates注入的筛选条件,筛选出具有负载均衡标识的 RestTemplate。
被@LoadBalanced注解的restTemplate会被定制,添加LoadBalancerInterceptor拦截器。
image.png
七. Ribbon 相关接口
源码入口RibbonClientConfiguration
- IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现,该策略能够在多区域环境下选出 最佳区域的实例进行访问。
- IPing:Ribbon的实例检查策略,默认采用DummyPing实现,该检查策略是一个特殊的实现,实际上 它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。
- ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现。
- ServerListFilter:服务实例清单过滤机制,默认采ZonePreferenceServerListFilter,该策略能够优先 过滤出与请求方处于同区域的服务实例。
- ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现,它具备了区域感知的能力。
八. Ribbon负载均衡策略
即IRule的实现
IRule实现
- RandomRule: 随机选择一个Server。
- RetryRule: 对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server。
- RoundRobinRule: 轮询选择, 轮询index,选择index对应位置的Server。
- AvailabilityFilteringRule: 过滤掉一直连接失败的被标记为circuit tripped的后端Server,并 过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其 实就是检查status里记录的各个Server的运行状态。
- BestAvailableRule: 选择一个最小的并发请求的Server,逐个考察Server,如果Server被 tripped了,则跳过。
- WeightedResponseTimeRule: 根据响应时间加权,响应时间越长,权重越小,被选中的可 能性越低。
- ZoneAvoidanceRule: 默认的负载均衡策略,即复合判断Server所在区域的性能和 Server的可用性选择Server,在没有区域的环境下,类似于轮询(RandomRule)
- NacosRule: 同集群优先调用
九.自定义负载均衡策略
自定义
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {
@Override
public Server choose(Object key) {
.... .... ....
return Server
}
}
全局生效
@Configuration
public class RibbonConfig {
/**
* 全局配置
* 指定负载均衡策略
* @return
*/
@Bean
public IRule() {
//
return new NacosRandomWithWeightRule();
}
}
局部生效
//修改application.yml
# 被调用的微服务名
mall‐order:
ribbon:
# 指定使用负载均衡策略
NFLoadBalancerRuleClassName: xxxx.NacosRandomWithWeightRule
十. 饥饿加载
开启饥饿加载,解决第一次调用慢的问题
ribbon:
eager‐load:
# 开启ribbon饥饿加载
enabled: true
# 配置mall‐user使用ribbon饥饿加载,多个使用逗号分隔
clients: mall‐order

