负载均衡

负载均衡是一种基础的网络服务,它的核心原理是按照指定的负载均衡算法,将请求分配到后端服务集群上,从而为系统提供并行处理和高可用的能力。提到负载均衡,你可能想到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配置和实现原理相关推荐

  1. Vue Router history模式的配置方法及其原理

    转载地址:https://segmentfault.com/a/1190000019391139 vue-router分为hash和history模式,前者为其默认模式,url的表现形式为http:/ ...

  2. 从Nacos客户端视角来分析一下配置中心实现原理

    目录 一 动态配置 1. 环境准备 2.新建配置 3.导入配置 4.配置客户端 5. 修改配置信息 6.小结 二  配置中心原理(推还是拉) 1.实例化 ConfigService 2.添加 List ...

  3. SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)...

    声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册 ...

  4. ribbon 配置 动态更新_SpringCloud实战三-Ribbon

    负载均衡 是一种计算机技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载,以达到最优化资源使用.最大化吞吐率.最小化响应时间.同时避免过载的目的. 传统项目,都使用 ...

  5. java 日志过期删除吗,log4j2 自动删除过期日志文件的配置及实现原理

    日志文件自动删除功能必不可少,当然你可以让运维去做这事,只是这不地道.而日志组件是一个必备组件,让其多做一件删除的工作,无可厚非.本文就来探讨下 log4j 的日志文件自动删除实现吧. 0.自动删除配 ...

  6. BOSHIDA 电源模块 PLC的硬件结构配置与工作原理

    BOSHIDA  电源模块 PLC的硬件结构配置与工作原理 中.大型PLC的结构外型,它通常采用积木式结构,可以根据需要将各种标准模块进行搭接,常用的模块有电源模块.CPU模块.输入模块.输出模块以及 ...

  7. 为Spring Cloud Ribbon配置请求重试(Camden.SR2+)

    当我们使用Spring Cloud Ribbon实现客户端负载均衡的时候,通常都会利用@LoadBalanced来让RestTemplate具备客户端负载功能,从而实现面向服务名的接口访问(原理可见& ...

  8. ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由

    前言 假设你有一个服务A,要调用服务B(有三个实例,B1.B2.B3),如何只调用其中的B1和B2,屏蔽掉B3?实际上解决方法大致分为两类. 一种是外部路由,就是通过网关等组件,在请求链路上进行路由选 ...

  9. springCloud入门学习(七):通过属性自定义Ribbon配置

    很多场景下,可能需要根据自定义的Riboon的配置,例如修改ribbon的负载均衡规则等. 配置前缀是:<clientName>.ribbon. NFLoadBalancerClassNa ...

最新文章

  1. 35个高级Python知识点总结
  2. 患者信息SQL v1
  3. java compareandset 包_在Java中,AtomicInteger compareAndSet()和synced关键字的性能如何?...
  4. Semtech的LoRa技术实现智能化工业应用管理
  5. 数字系统设计学习之QuartusII9的安装
  6. Animate.css
  7. python笔记03_IO编程
  8. matlab简单分析数字滤波器FIR
  9. hashmap value占用空间大小_如何获取 java hashmap占用存储空间空间大小
  10. 屏蔽五项网络功能 让XP系统极速狂飙
  11. 使用通达信获取股票历史数据
  12. 博微三维技术篇【七】——生态数据兼容
  13. 蔡学镛 java_转蔡学镛:该学Java或.NET,欢迎大家讨论,要对事不对人呵 - 第3页
  14. 项目保密协议书(范本)
  15. 机房搬迁实施规划方案
  16. 栈evaluate-reverse-polish-notation-leetcode练习题
  17. Linux下如何创建和取消软连接
  18. 数据仓库(六)---分布式SQL查询引擎---presto介绍
  19. 【Http请求工具类】
  20. SICP读书笔记 2.5

热门文章

  1. 微型计算机抽象原理,微机自动检测系统的结构原理及功能设计
  2. 选择大于努力,观念决定命运,智慧决定贫富
  3. 【Endnote】如何修改正文中参考文献的编号样式
  4. 依赖反转(倒置)原则(Dependency inversion principle,DIP)
  5. 人生就是修炼,修什么?
  6. 【论文翻译】Convolutional Oriented Boundaries
  7. 转自小木虫关于论文汇报的PPT
  8. 【高热FAQ】关于智慧康养物联网加速器 ,你想知道的都在这
  9. python UNIT5 函数 习题
  10. 数学基础----标准方差