ribbon
简介
Ribbon是Netflix发布的负载均衡器,它可以帮我们控制HTTP和TCP客户端的行为。只需为Ribbon配置服务提供者地址列表,Ribbon就可基于负载均衡算法计算出要请求的目标服务地址。
在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。
github地址
使用
为服务消费者整合ribbon
- 引用依赖
spring-cloud-starter-netflix-eureka-client
包含了ribbon依赖,如果引入了spring-cloud-starter-netflix-eureka-client
,则无需再引入ribbon依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 为restTemplate加上
@LoadBalanced
注解
只需加入@LoadBalanced
注解即可整合ribbon功能,使restTemplate具有负载均衡的能力
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
将请求地址改成微服务的虚拟主机名,当Ribbon和Eureka配合使用时,会自动将虚拟主机名映射成微服务的网络地址。
restTemplate.getForObject("http://virtualHostName/test", String.class);
可使用 LoadBalancerClient
的API更加直观地获取当前选择的用户微服务节点。但 loadBalancerClient.choose
和 restTemplate.getForObject
不能写在同一个方法中,两者会有冲突,因为此时代码中restTemplate实际上是一个Ribbon客户端,本身已经包含了“choose”的行为。
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("invokeMethod")
public void invokeMethod() {
String forObject = restTemplate.getForObject("http://eureka-client-producer/userInfo", String.class);
System.out.println(forObject);
}
@GetMapping("logUserInstance")
public void logUserInstance() {
ServiceInstance choose = this.loadBalancerClient.choose("eureka-client-producer");
System.out.println(choose.getServiceId()+" "+choose.getHost()+" "+choose.getPort());
}
}
虚拟主机名不能包含下划线(_),否则ribbon在调用时会报错:
Request URI does not contain a valid hostname
- 默认情况下,虚拟主机名和服务名称一致,也可以使用以下配置单独设置:
eureka:
instance:
#virtual-host-name或secure-virtual-host-name都可以
virtual-host-name: serverName
自定义配置
在Spring Cloud中,Ribbon的默认配置如下:
BeanType | BeanName | 默认类 | 作用 |
---|---|---|---|
IClientConfig | ribbonClientConfig | DefaultClientConfigImpl | 读取配置 |
IRule | ribbonRule | ZoneAvoidanceRule | 负载均衡规则,选择实例 |
IPing | ribbonPing | DummyPing (该类什么都不干,认为每个实例都可用,都能ping通) | 筛选掉ping不通的实例 |
ServerList<Server> | ribbonServerList | Ribbon:ConfigurationBasedServerList Spring Cloud Alibaba:NacosServerList | 交给Ribbon的实例列表 |
ServerListFilter<Server> | ribbonServerListFilter | ZonePreferenceServerListFilter | 过滤掉不符合条件的实例 |
ILoadBalancer | ribbonLoadBalancer | ZoneAwareLoadBalancer | Ribbon的入口 |
ServerListUpdater | ribbonServerListUpdate | PollingServerListUpdater | 更新交给Ribbon的List的策略 |
负载均衡的八种算法:
规则名称 | 作用 |
---|---|
AvailabilityFilteringRule | 过滤掉一直连接失败的被标记为circuit tripped(电路跳闸)的后端Service,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤Server的逻辑,其实就是检查status的记录的各个Server的运行状态 |
BestAvailableRule | 选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过 |
RandomRule | 随机选择一个Server |
已废弃,作用同WeightedResponseTimeRule | |
RetryRule | 对选定的负责均衡策略机上充值机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的Server |
RoundRobinRule | 轮询选择,轮询index,选择index对应位置Server |
WeightedResponseTimeRule | 根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低 |
ZoneAvoidanceRule | (默认是这个)负责判断Server所Zone的性能和Server的可用性选择Server,在没有Zone的环境下,类似于轮询(RoundRobinRule) |
使用java代码自定义配置(不推荐)
创建Ribbon配置类
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
//负载均衡规则改为随机
return new RandomRule();
}
}
使用配置类
@Configuration
@RibbonClient(name = "eureka-client-producer",configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
@RibbonClient中
name的值为特定的Ribbon Client自定义配置(生产者的虚拟主机名)
configration的值指定Ribbon的配置类
使用属性自定义配置
配置属性的方式比Java代码配置的方式优先级更高,这种方式比使用Java代码配置的方式更加方便。
支持的属性如下,配置的前缀是<clientName>.ribbon.。其中<clientName>是Ribbon Client的名称,如果省略,则表示全局配置。
- NFLoadBalancerClassName: 配置ILoadBalancer该接口实现类
- NFLoadBalancerRuleClassName: 配置IRule该接口实现类
- NFLoadBalancerPingClassName: 配置Iping该接口实现类
- NIWSServerListClassName: 配置ServerList该接口实现类
- NIWSServerListFilterClassName: 配置ServiceListFilter该接口实现类
使用如下形式表示对Ribbon Clienteureka-client-producer使用RandomRule负载均衡规则:
eureka-client-producer:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
使用如下形式表示对所有Ribbon Client使用RandomRule负载均衡规则:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
饥饿加载
Spring Cloud会为每个名称的Ribbon Client维护一个应用程序上下文,这个上下文默认是懒加载的。指定名称的Ribbon Client第一次请求时,对应的上下文才会被加载,因此,首次请求往往会比较慢。
在消费者配置文件中加上如下配置:
ribbon:
eager-load:
enabled: true
clients: client1,client2
这样对名为client1和client2的Ribbon Client,将在启动时就加载对应的子应用程序上下文,从而提高首次请求的访问速度。