Ribbon配置和实现原理
负载均衡
负载均衡是一种基础的网络服务,它的核心原理是按照指定的负载均衡算法,将请求分配到后端服务集群上,从而为系统提供并行处理和高可用的能力。提到负载均衡,你可能想到nginx。对于负载均衡,一般分为服务端负载均衡和客户端负载均衡。
- 服务端负载均衡:在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的负载均衡器,比如 F5,也有软件,比如 Nginx。
- 客户端负载均衡:所谓客户端负载均衡,就是客户端根据自己的请求情况做负载,本文介绍的Netflix Ribbon就是客户端负载均衡的组件。而Ribbon是一个客户端实现负载均衡的框架,主要用户客户端调用远端服务实现负载均衡。目前Ribbon使用的是spring-cloud-starter-netflix-ribbon这个依赖。
1.RestTemplate实现负载均衡
RestTemplate使用负载均衡,只需要给RestTemplate增加@LoadBalanced注解
@LoadBalanced@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
2.负载均衡策略配置
BestAvailableRule:在过滤掉故障服务后,它会基于过去30分钟的统计结果选取当前并发量最小的服务节点,也就是最“闲”的节点作为目标地址。如果统计结果尚未生成,则采用轮询的方式选定节点
ZoneAvoidanceRule: 包含了组合过滤条件,分别是Zone级别和可用性级别,Zone级别过滤为在Eureka注册中一个服务节点有Zone, Region和URL三个身份信息,其中Zone可以理解为机房大区(未指定则由Eureka给定默认值),而这里会对这个Zone的健康情况过滤其下面所有服务节点。可用性级别过滤和AvailabilityFilteringRule的验证非常像,会过滤掉当前并发量较大,或者处于熔断状态的服务节点
AvailabilityFilteringRule:这个规则底层依赖RandomRobinRule来选取节点,但并非来者不拒,必须要满足它的最低要求的节点才会被选中(节点处于非熔断状态和当前活跃请求数量不能超过阈值)。如果节点满足了要求,无论其响应时间或者当前并发量是什么,都会被选中
WeightedResponseTimeRule:这个Rule继承自RoundRibbonRule,他会根据服务节点的响应时间计算权重,响应时间越长权重就越低,响应越快则权重越高,权重的高低决定了机器被选中概率的高低。也就是说,响应时间越小的机器,被选中的概率越大
ResponseTimeWeightedRule:作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule
RoundRobinRule:默认策略,轮询选择,轮询 index,选择 index 对应位置的 Server
RandomRule:随机选择一个 Server
RetryRule:对选定的负载均衡策略机上重试机制,也就是说当选定了某个策略进行请求负载时在一个配置时间段内若选择 Server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 Server
2.1 配置负载均衡策略
方式1:代码方式
@Configuration
public class RibbonConfiguration {@Beanpublic IRule defaultLBStrategy() {return new RandomRule();}
方式2:配置文件方式
ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
2.2指定单个服务的负载均衡策略
方式1:代码方式
只需要在启动类或者配置类上增加注解
#这里的name指的是serviceId
@RibbonClient(name = "producer-one", configuration = com.netflix.loadbalancer.RoundRobinRule.class)
方式2:配置文件方式
producer-one.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
如果同时应用了以上两种方式去配置负载均衡,注解的优先级更高,因为配置文件的加载顺序在注解之前,后加载的配置会覆盖先前配置。
3.饥饿加载配置
Ribbon是在第一次方法调用的时候才去初始化LoadBalancer。这样看来,第一个方法请求不仅仅包含HTTP连接和方法的响应时间,还包括了LoadBalancer的创建耗时。假如你的方法本身就比较耗时的话,而且超时时间又设置的比较短,那么很大可能这第一次http调用就会失败。其实还有很多框架也实现了类似的懒加载功能,比如Hibernate的lazy-fetch,懒加载在大部分情况下可以节省系统资源开销,但某些情况下反而导致服务响应时间被延长。
#开启Ribbon的饥饿加载模式
ribbon.eager-load.enabled=true
#指定需要饥饿加载的服务名,若有多个则用逗号隔开
ribbon.eager-load.clients=producer-one
4.其他配置
4.1 脱离Eureka,单独使用ribbon
# 禁用 Eureka
ribbon.eureka.enabled=false# 禁用 Eureka 后手动配置服务地址
producer-one.ribbon.listOfServers=localhost:50000,localhost:50001
禁用了 Eureka 之后,就不能使用服务名称去调用接口了,必须指定服务地址。
4.2 其他配置
#控制ribbon下面的配置是否生效,默认true
ribbon.http.client.enabled=false# 请求连接的超时时间
ribbon.ConnectTimeout=2000
# 请求处理的超时时间
ribbon.ReadTimeout=2000
#不指定Ribbon默认使用轮询进行重试
ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule
# 在所有HTTP Method进行重试
ribbon.OkToRetryOnAllOperations=true
# 每台机器最大重试次数
ribbon.MaxAutoRetries=2
# 可以再重试几台机器
ribbon.MaxAutoRetriesNextServer=2#也可以为每个Ribbon客户端设置不同的超时时间, 通过服务名称进行指定:
#producer-one.ribbon-config-demo.ribbon.ConnectTimeout=2000
#producer-one.ribbon-config-demo.ribbon.ReadTimeout=500
ConnectTimeout:创建会话的连接时间,注意,不是服务的响应时间,而是本机与服务建立会话的时间。
ReadTimeout:当连接建立好之后,如果对方服务没有在规定时间内返回,则直接进行重试。
最大超时时间计算公式:MAX(Response Time) = (ConnectTimeout + ReadTimeout) * (MaxAutoRetries + 1) * (MaxAutoRetriesNextServer + 1)
5@LoadBalanced 注解原理
Spring Cloud 给我们做了大量的底层工作,我们使用RestTemplate实现负载均衡只需要加一个@LoadBalanced 就可以了,主要的逻辑就是给 RestTemplate 增加拦截器,在请求之前对请求的地址进行替换,或者根据具体的负载策略选择服务地址,然后再去调用。(可以查看源码org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration)。这里自定义一个@LoadBalanced来实现负责均衡。
1.新建一个拦截类MyLoadBalancerInterceptor
public class MyLoadBalancerInterceptor implements ClientHttpRequestInterceptor {private LoadBalancerClient loadBalancer;private LoadBalancerRequestFactory requestFactory;public MyLoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {this.loadBalancer = loadBalancer;this.requestFactory = requestFactory;}public MyLoadBalancerInterceptor(LoadBalancerClient loadBalancer) {this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));}@Overridepublic ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {final URI originalUri = request.getURI();String serviceName = originalUri.getHost();System.out.println("进入自定义的请求拦截器中" + serviceName);Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));}}
2.增加一个注解
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface MyLoadBalanced {
}
3.增加一个自动配置类,将拦截器对象放入Spring中
@Configuration
public class MyLoadBalancerAutoConfiguration {@MyLoadBalanced@Autowired(required = false)private List<RestTemplate> restTemplates = Collections.emptyList();@Beanpublic MyLoadBalancerInterceptor myLoadBalancerInterceptor(final LoadBalancerClient loadBalancer) {return new MyLoadBalancerInterceptor(loadBalancer);}@Beanpublic SmartInitializingSingleton myLoadBalancedRestTemplateInitializer(MyLoadBalancerInterceptor myLoadBalancerInterceptor) {return new SmartInitializingSingleton() {@Overridepublic void afterSingletonsInstantiated() {for (RestTemplate restTemplateTemp : MyLoadBalancerAutoConfiguration.this.restTemplates) {List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplateTemp.getInterceptors());list.add(myLoadBalancerInterceptor);restTemplateTemp.setInterceptors(list);}}};}
}
4.只需要将原来的@LoadBalanced替换成@MyLoadBalanced就可以了
参考:
SpringCloud系列之客户端负载均衡Netflix Ribbon - smileNicky - 博客园
SpringCloud Ribbon(二)之自定义负载均衡策略IRule_茅坤宝骏氹的博客-CSDN博客
Ribbon配置和实现原理相关推荐
- Vue Router history模式的配置方法及其原理
转载地址:https://segmentfault.com/a/1190000019391139 vue-router分为hash和history模式,前者为其默认模式,url的表现形式为http:/ ...
- 从Nacos客户端视角来分析一下配置中心实现原理
目录 一 动态配置 1. 环境准备 2.新建配置 3.导入配置 4.配置客户端 5. 修改配置信息 6.小结 二 配置中心原理(推还是拉) 1.实例化 ConfigService 2.添加 List ...
- SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)...
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册 ...
- ribbon 配置 动态更新_SpringCloud实战三-Ribbon
负载均衡 是一种计算机技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载,以达到最优化资源使用.最大化吞吐率.最小化响应时间.同时避免过载的目的. 传统项目,都使用 ...
- java 日志过期删除吗,log4j2 自动删除过期日志文件的配置及实现原理
日志文件自动删除功能必不可少,当然你可以让运维去做这事,只是这不地道.而日志组件是一个必备组件,让其多做一件删除的工作,无可厚非.本文就来探讨下 log4j 的日志文件自动删除实现吧. 0.自动删除配 ...
- BOSHIDA 电源模块 PLC的硬件结构配置与工作原理
BOSHIDA 电源模块 PLC的硬件结构配置与工作原理 中.大型PLC的结构外型,它通常采用积木式结构,可以根据需要将各种标准模块进行搭接,常用的模块有电源模块.CPU模块.输入模块.输出模块以及 ...
- 为Spring Cloud Ribbon配置请求重试(Camden.SR2+)
当我们使用Spring Cloud Ribbon实现客户端负载均衡的时候,通常都会利用@LoadBalanced来让RestTemplate具备客户端负载功能,从而实现面向服务名的接口访问(原理可见& ...
- ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由
前言 假设你有一个服务A,要调用服务B(有三个实例,B1.B2.B3),如何只调用其中的B1和B2,屏蔽掉B3?实际上解决方法大致分为两类. 一种是外部路由,就是通过网关等组件,在请求链路上进行路由选 ...
- springCloud入门学习(七):通过属性自定义Ribbon配置
很多场景下,可能需要根据自定义的Riboon的配置,例如修改ribbon的负载均衡规则等. 配置前缀是:<clientName>.ribbon. NFLoadBalancerClassNa ...
最新文章
- 提分策略:数据采样方法最全总结!
- python js 效率_巧用 db.system.js 提升20% 开发效率
- java用栈处理四则运算_Java 用栈处理四则运算
- 如何彻底解决烦人的 MySQL 分库分表问题?写一个更好的数据库!
- 调用dll 返回65535_一种通用DLL劫持技术研究
- 如果命运是一条孤独的河流,谁会是你的灵魂摆渡人
- NANDFlash原理
- php 获取当前域名
- word打开文档很久很慢_打开office非常慢怎么回事_电脑打开word文件很慢怎么办
- 2021零基础学习人工智能(AI)思想篇
- 34Speech SIMCLR: Combining Contrastive and Reconstruction Objective for Self-supervised Speech
- 《只为遇见你》硬生生把爱情片拍成了把妹宝典,真人出镜演绎直男转型
- Docker常用命令大全(万字详解)
- 申请苹果个人开发者账号流程
- 在App Store和Google Play上推广应用程序
- 旧服务器系统迁移移到虚拟机,服务器不关机进行虚拟机的迁移,vMotion 迁移
- python-英雄联盟购买界面
- 【Flutter】Dart 数据类型 List 集合类型 ( 定义集合 | 初始化 | 泛型用法 | 初始化后添加元素 | 集合生成函数 | 集合遍历 )
- jenkins api java封装_Jenkins api java 调用
- Ubuntu16.04-ros-kinetic激光避障、导航小车