目录
前言
Ribbon
是一个Netflix
开源的客户端侧负载均衡器,其提供了丰富的负载均衡算法,服务消费者集成Ribbon
后,Ribbon
会自动从Nacos Server
获取想要调用的服务的地址列表,通过负载均衡算法计算出一个实例交给RestTemplate
调用
注:Spring Cloud 2020 已移除对 Ribbon 的支持,相应的,Spring Cloud 2021 版本 Nacos 中 也删除了Ribbon 的 jar 包,实现时需要注意版本依赖关系
环境
Spring Cloud Hoxton.SR9 + Spring Cloud Alibaba 2.2.6.RELEASE
简单示例
spring-cloud-starter-alibaba-nacos-discovery
中默认包含Ribbon
,所以不需要添加依赖
这里的示例代码是内容中心(content-center)通过调用用户中心(user-center)的两个实例看是否实现负载均衡
user-center
TestController.java
@RestController
@Slf4j
public class TestController {
@GetMapping("/test/{name}")
public String test(@PathVariable String name) {
log.info("请求...");
return "hello " + name;
}
}
- 用户中心以
8081
,8082
端口启动
content-center
- 启动类
/**
* @LoadBalanced 为RestTemplate 整合Ribbon
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
TestController.java
@RestController
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
private final RestTemplate restTemplate;
/**
* 整合Ribbon
* @return
*/
@GetMapping("test3")
public String test3() {
/**
* RestTemplate 请求时,ribbon会把user-center转换成用户中心在Nacos上的地址,
* 进行负载均衡算法计算出一个实例去请求
*/
return restTemplate.getForObject(
"http://user-center/test/{name}",
String.class,
"Coisini"
);
}
}
测试
- 访问接口测试,可以发现
Ribbon
以轮询的方式实现负载均衡
Ribbon 的组成和默认的负载均衡规则
Ribbon 的组成
Ribbon
为所有的组件提供了接口,如果对默认值不满意,可以实现这些接口进行二次开发
接口 | 作用 | 默认值 |
---|---|---|
IClientConfig | 读取配置 | DefaultClientConfigImpl |
IRule | 负载均衡规则,选择实例 | ZoneAvoidanceRule |
IPing | 筛选掉ping不通的实例 | DummyPing |
ServerList< Server> | 交给Ribbon的实例列表 | Ribbon:ConfigurationBasedServerList Spring Cloud Alibaba: NacosServerList |
ServerListFilter< Server> | 过滤掉不符合条件的实例 | ZonePreferenceServerListFilter |
ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
ServerListUpdater | 更新交给Ribbon的List的策略 | PollingServerListUpdater |
Ribbon 默认的负载均衡规则
Ribbon
默认的负载均衡规则是ZoneAvoidanceRule
,在没有zone
的情况下默认是轮询Ribbon
内置的负载均衡规则如下
规则名称 | 特点 |
---|---|
AvailabilityFilteringRule | 过滤掉一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就是检查status里记录的各个Server的运行状态 |
BestAvailableRule | 选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过 |
RandomRule | 随机选择一个Server |
ResponseTimeWeightedRule | 已废弃,作用同WeightedResponseTimeRule |
RetryRule | 对选定的负载均衡策略机上重试机制,在同一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的Server |
RoundRobinRule | 轮询选择,轮询index,选择index对应位置的Server |
WeightedResponseTimeRule | 根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低 |
ZoneAvoidanceRule | 复合判断Server所在Zone的性能和Server的可用性选择Server,在没有Zone的环境下,类似于轮询(RoundRobinRule) |
Ribbon 的自定义配置
实现目的:通过自定义配置实现随机选择
Java 代码配置方式
UserCenterRibbonConfiguration.java
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
import ribbonconfiguration.RibbonConfiguration;
/**
* @Description 用户中心配置类
*/
@Configuration
@RibbonClient(name = "user-center", configuration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
RibbonConfiguration.java
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Ribbon的配置类
* Ribbon的配置类要有@Configuration注解,但不能被@ComponentScan重复扫描
* 否则就会被所有的RibbonClient共享
*/
@Configuration
public class RibbonConfiguration {
/**
* 自定义负载均衡规则
* RandomRule 随机选择
* @return
*/
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
- 目录结构如下所示,
Ribbon
配置类RibbonConfiguration.java
位置在java
目录下,其作用是避免父子上下文重叠,Ribbon
的配置类要有@Configuration
注解,但不能被@ComponentScan
重复扫描,否则就会被所有的RibbonClient
共享
- 接口访问测试发现随机访问已实现
yml 属性配置方式
- 注释
Java
代码配置方式中的代码,在application.yml
中添加user-center
的负载均衡规则,也能实现相同的效果
user-center:
ribbon:
# Ribbon负载均衡规则的全路径
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Ribbon 的全局配置
- 有自定义配置就有全局配置,可以通过修改
@RibbonClient
注解为@RibbonClients
注解实现全局配置 UserCenterRibbonConfiguration.java
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Configuration;
import ribbonconfiguration.RibbonConfiguration;
/**
* @Description 用户中心配置类
*/
@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {
}
RibbonConfiguration.java
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description Ribbon的配置类
*/
@Configuration
public class RibbonConfiguration {
/**
* 自定义负载均衡规则
* RandomRule 随机选择
* @return
*/
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
Ribbon 的饥饿加载
-
默认情况下
Ribbon
是懒加载的,当RestTemplate
第一次调用RibbonClient
时才会创建一个client
,这样会导致首次请求过慢或失败的问题,可以通过属性配置开启Ribbon
的饥饿加载 -
application.yml
ribbon:
eager-load:
# 开启饥饿加载
enabled: true
# 为哪些RibbonClient开启饥饿加载,多个用 "," 隔开
clients: user-center
项目源码
GitHub
: https://github.com/Maggieq8324/coisini-cloud-alibabaGitee
: https://gitee.com/maggieq8324/coisini-cloud-alibaba