ribbon负载均衡,ribbon负载均衡详解
ribbon负载均衡,ribbon负载均衡详解详细介绍
本文目录一览: Ribbon-负载均衡策略
负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而今天的主角Ribbon就是属于后者--客户端负载均衡器。
服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足一同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客户端负载均衡就提供了这种灵活性。 然而客户端负载均衡也有其缺点,如果配置不当,可能会导致服务提供者出现热点,或者压根就拿不到任何服务的情况。及了解一下Ribbon的7种内置负载均衡策略的具体规则。
Ribbon是Spring Cloud技术栈中非常重要的基础框架,它为Spring Cloud提供了负载均衡的能力,比如Fegin和OpenFegin都是基于Ribbon实现的,就连Nacos中的负载均衡也使用了Ribbon框架。
Ribbon框架的强大之处在于,它不仅内置了7种负载均衡策略,同时还支持用户自定义负载均衡策略,所以其开放性和便利性也是它得以流行的主要原因。
服务端负载均衡和客户端负载均衡的区别如下所示:
客户端负载均衡器的实现原理是通过注册中心,如Nacos,将可用的服务列表拉取到本地(客户端),在通过客服端负载均衡器(设置的负载均衡策略)获取到某个服务器的具体IP和端口,然后在通过HTTP框架请求服务并得到结果,其执行流程如下所示:
以Nacos中Ribbon负载均衡设置为例,在配置文件 application.yml 中设置如下配置即可:
因为Nacos中已经内置了Ribbon,所以在实现项目开发中无需再引用Ribbon依赖了,这一点我们在Nacos的依赖树中就可以看到,如下所示:
轮询策略:RoundRobinRule,按照一定的顺序依次调用服务实例。比如一共有 3 个服务,第一次调用服务 1,第二次调用服务 2,第三次调用服务3,依次类推。此策略的配置设置如下:
权重策略:WeightedResponseTimeRule,根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。它的实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率也越大。此策略的配置设置如下:
随机策略:RandomRule,从服务提供者的列表中随机选择一个服务实例。此策略的配置设置如下:
最小连接数策略:BestAvailableRule,也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的一个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。此策略的配置设置如下:
重试策略:RetryRule,按照轮询策略来获取服务,如果获取的服务实例为null或已经失效,则在指定的时间之内不断地进行重试来获取服务。如果超过指定时间依然没获取到服务实例则返回null。此策略的配置设置如下:
可用敏感性策略:AvailabilityFilteringRule,先过滤掉非健康的服务实例,然后在选择连接数较小的服务实例。此策略的配置设置如下:
区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。此策略的配置设置如下:
Ribbon 为客户端负载均衡器,相比于服务端负载均衡器的统一负载均衡策略来说,它提供了更多的灵活性。Ribbon 内置了 7 种负载均衡策略:轮询策略、权重策略、随机策略、最小连接数策略、重试策略、可用性敏感策略、区域性敏感策略,并且用户可以通过继承 RoundRibbonRule 来实现自定义负载均衡策略。
ribbon负载均衡详解
服务端负载均衡:在客户端和服务端中间使用代理,lvs? 和 nginx。
硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端端地址,然后进行转发。
客户端负载均衡:根据自己的情况做负载。Ribbon。
客户端负载均衡和服务端负载均衡最大的区别在于 服务端地址列表的存储位置,以及负载算法在哪里。
2、Spring Cloud的负载均衡机制的实现
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Ribbon实现客户端的负载均衡,负载均衡器提供很多对http和tcp的行为控制。Spring cloud Feign已经集成Ribbon,所以注解@FeignClient的类,默认实现了ribbon的功能。
Ribbon主要包括如下功能
1.支持通过DNS和IP和服务端通信
2.可以根据算法从多个服务中选取一个服务进行访问
3.通过将客户端和服务器分成几个区域(zone)来建立客户端和服务器之间的关系。客户端尽量访问和自己在相同区域(zone)的服务,减少服务的延迟
4.保留服务器的统计信息,ribbon可以实现用于避免高延迟或频繁访问故障的服务器
5.保留区域(zone)的统计数据,ribbon可以实现避免可能访问失效的区域(zone)
Ribbon负载均衡主要是通过LoadBalancerClient类实现的,而LoadBalancerClient又将具体处理委托给ILoadBalancer处理;
每个服务都有一个ILoadBalancer,ILoadBalancer里面有该服务列表。
每个服务 Map
ILoadBalancer通过配置IRule、IPing等信息,并通过ServerList获取服务器注册列表的信息,默认以每10s的频率想服务列表中每个服务实例发送ping请求,检测服务实例是否存活,最后使用负责均衡策略对ServerListFilter过滤得到最终可用的服务实例列表进行处理,然后交给服务调用器进行调用;
ILoadBalance也是一个接口,提供了3个具体实现,分别是DynamicServerListLoadBalancer、ZoneAwareLoadBalancer和NoOpLoadBalancer;
DynamicServerListLoadBalancer继承自ILoadBalancer基础实现BaseLoadBalancer,在基础的负载均衡功能上增加了运行期间对服务实例动态更新和过滤的功能;
NoOpLoadBalancer没有操作的实现;
ZoneAwareLoadBalancer(ILoadBalancer的默认的实现类是:ZoneAwareLoadBalancer。)则是继承DynamicServerListLoadBalancer,在此基础上增加防止跨区域访问的问题;
首先它会剔除符合这些规则的Zone区域:所属实例数位零的Zone区域;Zone区域内实例等平均负载小于零,或者实例故障率(断路器断开次数/实例数)大于等于阀值(默认为0.99999)。
然后根据Zone区域等实例平均负载计算出最差的Zone区域,这里的最差指的是实例平均负载最高的Zone区域。
如果在上面的过程中没有符合剔除要求的区域,同时实例最大平均负载小于阀值(默认为20%),就直接返回所有Zone区域为可用区域。否则,从最坏Zone区域集合中随机选择一个,将它从可用Zone区域集合中剔除。
???当获得的可用Zone区域集合不为空,并且个数小于Zone区域总数,就随机选择一个Zone区域。
??在确定了某个Zone区域后,则获取了对应Zone区域的服务均衡器,并调用chooseServer来选择具体的服务实例,而在chooseServer中将使用IRule接口的choose函数来选择具体的服务实例。在这里,IRule接口的实现会使用ZoneAvoidanceRule来挑选出具体的服务实例。
服务列表就是客户端负载均衡所使用的(同一注册中心集群)各服务的服务实例列表。Ribbon在实现上支持以下几种服务列表方式
静态服务器列表:通过Ribbon的BaseLoadBalancer所提供的setServerList()方法,初始化时直接进行动态设置指定;
基于配置的服务器列表:需要在项目配置文件中通过
.ribbon.listOfServers进行设置。(如user-service.ribbon.listOfServers=http://127.0.0.1:8082,http://127.0.0.1:8083)
基于服务发现的服务器列表:同时使用Ribbon和Eureka时,默认使用该方式,在应用启动时Ribbon就会从Eureka服务器中获取所有注册服务的列表数据,并保持同步。
该组件会对原始服务列表使用一定策略进行过滤返回有效可用的服务器列表给客户端负载均衡器使用。常用服务列表过滤器如下:ZoneAffinityServerListFilter:基于区域感知的方式,实现对服务实例的过滤,仅返回与本身所处区域一直的服务提供者实例列表;ServerListSubsetFilter:该过滤器继承自ZoneAffinityServerListFilter,在进行区域感知过滤后,仅返回一个固定大小的服务列表。默认将返回20个服务实例,可以通过ribbon.ServerListSubsetFilter.size进行设置;
ZonePreferenceServerListFilter:使用Eureka和Ribbon时默认的过滤器。实现通过配置或者Eureka所属区域来过滤出同区域的服务实例列表。
它实现了通过配置或者Eureka实例元数据的所属区域(Zone)来过滤出同区域的服务实例。如下面的源码所示,它的实现非常简单,首先通过父类ZoneAffinityServerListFilter的过滤器来获得“区域感知”的服务实例列表,然后遍历这个结果,取出根据消费者配置预设的区域Zone来进行过滤,如果过滤掉结果是空就直接返回父类获取的结果,如果不为空就返回通过消费者配置的Zone过滤后的结果。
用来检测一个微服务实例是否存活是否有响应,Ribbon通过该组件来判断所持有的服务实例列表中各服务可用情况,如果检测到某服务实例不存在/一定时间未响应,则会从持有服务列表中及时移除。
PingUrl:通过定期访问指定的URL判断;
PingConstant:不做任何处理,只返回一个固定值,用来表示该服务是否可用,默认值为true;
NoOpPing:不做任何处理,直接返回true,表示该服务器可用,默认策略;
DummyPing:直接返回true,但实现了initWithNiwsConfig方法;
NIWSDiscoverPing:根据DiscoveryEnabledServer中InstanceInfo的InstanceStatus属性判断,如果该属性的值为InstanceStatus.UP,则表示服务器可用;
作用就是选择一个最终服务实例地址作为负载均衡处理结果。Ribbon提供的选择策略有随机 (Random)、轮询 (RoundRobin)、一致性哈希 (ConsistentHash)、哈希 (Hash)、加权(Weighted)。
IRule负载均衡策略:通过实现该接口定义自己的负载均衡策略。它的choose方法就是从一堆服务器列表中按规则选出一个服务器。
默认实现:
ZoneAvoidanceRule(区域权衡策略):复合判断Server所在区域的性能和Server的可用性,轮询选择服务器。
其他规则:
BestAvailableRule(最低并发策略):会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。逐个找服务,如果断路器打开,则忽略。
RoundRobinRule(轮询策略):以简单轮询选择一个服务器。按顺序循环选择一个server。
RandomRule(随机策略):随机选择一个服务器。
AvailabilityFilteringRule(可用过滤策略):会先过滤掉多次访问故障而处于断路器跳闸状态的服务和过滤并发的连接数量超过阀值得服务,然后对剩余的服务列表安装轮询策略进行访问。
WeightedResponseTimeRule(响应时间加权策略):据平均响应时间计算所有的服务的权重,响应时间越快服务权重越大,容易被选中的概率就越高。刚启动时,如果统计信息不中,则使用RoundRobinRule(轮询)策略,等统计的信息足够了会自动的切换到WeightedResponseTimeRule。响应时间长,权重低,被选择的概率低。反之,同样道理。此策略综合了各种因素(网络,磁盘,IO等),这些因素直接影响响应时间。
RetryRule(重试策略):先按照RoundRobinRule(轮询)的策略获取服务,如果获取的服务失败则在指定的时间会进行重试,进行获取可用的服务。如多次获取某个服务失败,就不会再次获取该服务。主要是在一个时间段内,如果选择一个服务不成功,就继续找可用的服务,直到超时。
1.
:这是调用ribbon的客户端名称,如果此值为没有配置,则此条属性会作用到所有的客户端。
2.
:默认值为 “ribbon”
3.
:所有的可用的属性都在com.netflix.client.conf.CommonClientConfigKey。
.
.NFLoadBalancerClassName=xx
.
.NFLoadBalancerRuleClassName=xx
.
.NFLoadBalancerPingClassName=xx
.
.NIWSServerListClassName=xx
.
.NIWSServerListFilterClassName=xx
com.netflix.client.config.IClientConfig:Ribbon的客户端配置,默认采用com.netflix.client.config.DefaultClientConfigImpl实现。
com.netflix.loadbalancer.IRule:Ribbon的负载均衡策略,默认采用com.netflix.loadbalancer.ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。
com.netflix.loadbalancer.IPing:Ribbon的实例检查策略,默认采用com.netflix.loadbalancer.NoOpPing实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。
com.netflix.loadbalancer.ServerList:服务实例清单的维护机制,默认采用com.netflix.loadbalancer.ConfigurationBasedServerList实现。
com.netflix.loadbalancer.ServerListFilter:服务实例清单过滤机制,默认采org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter,该策略能够优先过滤出与请求方处于同区域的服务实例。
com.netflix.loadbalancer.ILoadBalancer:负载均衡器,默认采用com.netflix.loadbalancer.ZoneAwareLoadBalancer实现,它具备了区域感知的能力。
上面的配置是在项目中没有引入spring Cloud Eureka,如果引入了Eureka和Ribbon依赖时,自动化配置会有一些不同。
通过自动化配置的实现,可以轻松的实现客户端的负载均衡。同时,针对一些个性化需求,我们可以方便的替换上面的这些默认实现,只需要在springboot应用中创建对应的实现实例就能覆盖这些默认的配置实现。
@Configuration
public class MyRibbonConfiguration {
? ? @Bean
? ? public IRule ribbonRule(){
? ? ? ? return new RandomRule();
? ? }
}
这样就会使用P使用了RandomRule实例替代了默认的com.netflix.loadbalancer.ZoneAvoidanceRule。
也可以使用@RibbonClient注解实现更细粒度的客户端配置
对于Ribbon的参数通常有二种方式:全局配置以及指定客户端配置
全局配置的方式很简单
只需要使用ribbon.
=
格式进行配置即可。其中,
代表了Ribbon客户端配置的参数名,
则代表了对应参数的值。比如,我们可以想下面这样配置Ribbon的超时时间
ribbon.ConnectTimeout=250
ribbon.ServerListRefreshInterval=2000? ?ribbon获取服务定时时间
全局配置可以作为默认值进行设置,当指定客户端配置了相应的key的值时,将覆盖全局配置的内容
指定客户端的配置方式
.ribbon.
=
的格式进行配置.
表示服务名,比如没有服务治理框架的时候(如Eureka),我们需要指定实例清单,可以指定服务名来做详细的配置,
user-service.ribbon.listOfServers=localhost:8080,localhost:8081,localhost:8082
对于Ribbon参数的key以及value类型的定义,可以通过查看com.netflix.client.config.CommonClientConfigKey类。
当在spring Cloud的应用同时引入Spring cloud Ribbon和Spring Cloud Eureka依赖时,会触发Eureka中实现的对Ribbon的自动化配置。这时的serverList的维护机制实现将被com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList的实例所覆盖,该实现会讲服务清单列表交给Eureka的服务治理机制来进行维护。IPing的实现将被com.netflix.niws.loadbalancer.NIWSDiscoveryPing的实例所覆盖,该实例也将实例接口的任务交给了服务治理框架来进行维护。默认情况下,用于获取实例请求的ServerList接口实现将采用Spring Cloud Eureka中封装的org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList,其目的是为了让实例维护策略更加通用,所以将使用物理元数据来进行负载均衡,而不是使用原生的AWS AMI元数据。在与Spring cloud Eureka结合使用的时候,不需要再去指定类似的user-service.ribbon.listOfServers的参数来指定具体的服务实例清单,因为Eureka将会为我们维护所有服务的实例清单,而对于Ribbon的参数配置,我们依然可以采用之前的两种配置方式来实现。
此外,由于spring Cloud Ribbon默认实现了区域亲和策略,所以,可以通过Eureka实例的元数据配置来实现区域化的实例配置方案。比如可以将不同机房的实例配置成不同的区域值,作为跨区域的容器机制实现。而实现也非常简单,只需要服务实例的元数据中增加zone参数来指定自己所在的区域,比如:
eureka.instance.metadataMap.zone=shanghai
在Spring Cloud Ribbon与Spring Cloud Eureka结合的工程中,我们可以通过参数禁用Eureka对Ribbon服务实例的维护实现。这时又需要自己去维护服务实例列表了。
ribbon.eureka.enabled=false.
由于Spring Cloud Eureka实现的服务治理机制强调了cap原理的ap机制(即可用性和可靠性),与zookeeper这类强调cp(一致性,可靠性)服务质量框架最大的区别就是,Eureka为了实现更高的服务可用性,牺牲了一定的一致性,在极端情况下宁愿接受故障实例也不要丢弃"健康"实例。
比如说,当服务注册中心的网络发生故障断开时候,由于所有的服务实例无法维护续约心跳,在强调ap的服务治理中将会把所有服务实例剔除掉,而Eureka则会因为超过85%的实例丢失心跳而触发保护机制,注册中心将会保留此时的所有节点,以实现服务间依然可以进行互相调用的场景,即使其中有部分故障节点,但这样做可以继续保障大多数服务的正常消费。
在Camden版本,整合了spring retry来增强RestTemplate的重试能力,对于我们开发者来说,只需要简单配置,即可完成重试策略。
spring.cloud.loadbalancer.retry.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
user-service.ribbon.ConnectTimeout=250
user-service.ribbon.ReadTimeout=1000
user-service.ribbon.OkToRetryOnAllOperations=true
user-service.ribbon.MaxAutoRetriesNextServer=2
user-service.ribbon.maxAutoRetries=1
spring.cloud.loadbalancer.retry.enabled:该参数用来开启重试机制,它默认是关闭的。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:断路器的超时时间需要大于Ribbon的超时时间,不然不会触发重试。
user-service.ribbon.ConnectTimeout:请求连接超时时间。
user-service.ribbon.ReadTimeout:请求处理的超时时间
user-service.ribbon.OkToRetryOnAllOperations:对所有操作请求都进行重试。
user-service.ribbon.MaxAutoRetriesNextServer:切换实例的重试次数。
user-service.ribbon.maxAutoRetries:对当前实例的重试次数。
根据以上配置,当访问到故障请求的时候,它会再尝试访问一次当前实例(次数由maxAutoRetries配置),如果不行,就换一个实例进行访问,如果还是不行,再换一个实例访问(更换次数由MaxAutoRetriesNextServer配置),如果依然不行,返回失败
项目启动的时候会自动的为我们加载LoadBalancerAutoConfiguration自动配置类,该自动配置类初始化条件是要求classpath必须要有RestTemplate这个类,必须要有LoadBalancerClient实现类。
LoadBalancerAutoConfiguration为我们干了二件事,第一件是创建了LoadBalancerInterceptor拦截器bean,用于实现对客户端发起请求时进行拦截,以实现客户端负载均衡。创建了一个
RestTemplateCustomizer的bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器。
每次请求的时候都会执行org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor的intercept方法,而LoadBalancerInterceptor具有LoadBalancerClient(客户端负载客户端)实例的一个引用,
在拦截器中通过方法获取服务名的请求url(比如http://user-service/user),及服务名(比如user-service),然后调用负载均衡客户端的execute方法。
执行负载客户端RibbonLoadBalancerClient(LoadBalancerClient的实现)的execute方法,得到ILoadBalancer(负载均衡器)的实现ZoneAwareLoadBalancer,并且通过调用其chooseServer方法获得服务列表中的一个实例,比如说user-service列表注册到eureka中一个实例。然后向其中的一个具体实例发起请求,得到结果。
Ribbon详解?
https://www.jianshu.com/p/1bd66db5dc46
Spring cloud系列六 Ribbon的功能概述、主要组件和属性文件配置??
https://blog.csdn.net/hry2015/article/details/78357990
Ribbon的ZoneAwareLoadBalancer??
https://blog.csdn.net/chengqiuming/article/details/81209131
Ribbon的实际使用
https://www.jianshu.com/p/f86af82fa782
本人有道云笔记中记录的参考文章
文档:04_ribbon 负载均衡.note
链接:http://note.youdao.com/noteshare?id=74e2434f21c3e96fb106be44fd8ed0b9&sub=2516B0E6DFEE4786B26D9528AF522928
服务名称>
服务名,iloadbalancer>
Springcloud + nacos + gateway 负载均衡(ribbon)
Ribbon是客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用
负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。 负载均衡构建在原有网络结构之上,它提供了一种透明且廉价有效的方法扩展服务器和网络设备的带宽、加强网络数据处理能力、增加吞吐量、提高网络的可用性和灵活性
本文主要测试,在Springcloud + nacos + gateway基础上,如何实现负载平衡
前面我们已经整合了Springcloud + nacos + gateway,实现了,当启动3个provider时候,通过gateway,可以对该3个provider进行轮询
1 nocas负载均衡。
? ?a nocas本身已集成了ribbon,默认使用轮询的方式
? ?b 在nocas设置weight,实现权重的方式
? ?c 自定rule(IRule实现类)
? ?d 顺提,在权重的方式下,可使用先设置权重为0,再关闭单一服务的方式,优雅地下线服务
2 使用ribbon直连ip
? ?a 使用ribbon提供的自动策略,轮询,随机等
? ?b 健康检查
? ?v 自定义rule
关掉其中一个provider,立即通过gateway进行轮询,发现gateway仍然会call已经down掉的provider,导致查询失败。但在大约5秒后,轮询恢复正常,不再call已经prodiver.
gateway call provider首先经nacos注册中心,nacos心跳机制默认每5秒钟检查一次provider是否正常,因此就会出现上面现象。
1 在启动类,将配置类 将IRule 的实现类注册到spring容器中即可
2 分别测试轮询和随机,可正常按规则负载
1 增加gatewayriboonip模块
2 pom添加依赖spring-cloud-starter-gateway和spring-cloud-starter-netflix-ribbon
3 修改application.yml,设置负载均衡
4 启动,测试可正常进行轮询
5?修改application.yml 如下,可测试到从轮询方式变成了随机的方式
? ?NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
这个时候down掉一个provider,然后轮询,到这个provider时候,会一直查询失败。我们需要增加一个健康检查处理,在服务down掉的时候,可感知到并将该服务从服务列表去除,在服务上线后,可检查到服务已上线
1 增加健康检查
? ?provider模块增加rest接口HealthController
? ?增加config类,产生RestTemplate
? ?增加健康检查类HealthExamination implements IPing。继承IPing接口,判断服务是否可用。我们在微服务中增加heath接口,在gateway中调用该接口,如果返回正常则认为微服务可用。
? ??修改application.yml 增加Ping如下
? ? ? ? ??NFLoadBalancerPingClassName: com.roy.springnacos.gatewayribbonip.loadBalance.HealthExamination
2 重启provider和gateway,进行测试
? ?a 轮询成功
? ?b down掉其中一个provider,轮询到该provider时候,查询失败
? ? 这里测试未能成功,使用RoundRobinRule还是一直出现查询失败,未能自动skip掉down掉的provider
? ?但是自定义LoadBalancerRule的话,是能够成功skip掉down掉的provide的
1 增加MyRule extends AbstractLoadBalancerRule
2 重启后,测试成功按规则查询
Spring Cloud客户端负载均衡 - Ribbon
注册restTemplate
使用restTemplate发送GET请求
通过@LoadBalanced注解可知该注解用来给restTemplate做标记,使用客户端负载均衡进行配置,搜索LoadBalancerClient类
ServiceInstanceChooser用来根据serviceId进行选择服务
通过以上得知,客户端负载均衡器应具备的几种能力
LoadBalancerAutoConfiguration为实现客户端负载均衡器的自动化配置类
该配置类需要满足两个条件
在示例中没有retryTemplate,则会创建一个LoadBalancerInterceptor对象
在LoadBalancerInterceptor的构造方法中注入了LoadBalancerClient的实现
当一个被@LoadBalance标注的RestTemplate向外发送Http请求时,会被interceptor拦截,调用execute发起实际请求
LoadBalancerClient的具体实现为org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient
execute方法
首先根据传入的serviceId获取具体的服务实例
根据getServer接口,可知并没有使用choose函数,而是使用了ribbon本身的chooseServer函数
在ribbonClientConfiguration中可知默认采用了ZoneAwareLoadBalancer实现负载均衡器
回到RibbonBalancerClient的execute函数
通过ZoneAwareLoadBalancer的chooseServer获取负载均衡策略分配到的服务实例后,将其包装成RibbonServer对象,RibbonServer对象除了包含服务实例对象外,还包含serviceId等信息,然后使用该对象回调LoadBalancerInteceptor请求拦截器中LoadBalancerRequest的apply函数,向一个实际的具体服务发起请求
ServiceInstance对象是对服务的抽象定义,包含了每个服务实例需要提供一些基础信息
而RibbonServer就是ServiceInstance的实现,除了Server实例,还包含了serviceId,是否使用https,和一个map的元数据
在LoadBalanceRequest的工厂方法中
传入了一个ServiceRequestWrapper对象
在LoadBalanceRequest的工厂方法中的execute具体执行时,会调用InteceptingClientHttpRequest下的execute函数
而这里面的request.getUri则会调用ServiceRequestWrapper中LoadBalancerClient的getUri函数,至此构建了一个服务治理环境的访问URI,完成代理访问
AbstractLoadBalancer
是ILoadBalancer的抽象实现,定义了服务的分组枚举类,实现了chooseServer,参数key为null,表示在选择具体服务实例时忽略key的条件判断
LoadBalancerStats用来记录负载均衡器中哥哥服务实例的属性和统计信息
getServerList根据分组类型来获取不同的服务实例列表
BaseLoadBalancer
是ribbon负载均衡器的基础实现类,在该类中定义了很多关于负载均衡器相关的基础内容
定义了所有服务清单和正常清单
定义了检查服务实例操作的执行策略对象,默认为SerialPingStrategy
SerialPingStrategy默认采用遍历方式,性能欠佳,如有需要,可以实现IPingStrategy并重写pingServers方法
定义了负载均衡的处理IRule对象,负载均衡策略委托给IRule,而默认的实现为RoundRobinRule
启动ping任务
是BaseLoadBalancer的拓展,该负载均衡器提供了运行期间动态更新服务实例清单的能力,在成员定义中可发现
T在类名中限定为Server的子类
ServerList提供了两个抽象方法
在spring cloud整合ribbon和eureka的包下搜索EurekaRibbonClientConfiguration
DiscoveryEnabledNIWSServerList内部获取serverlist通过内部私有函数obtainServersViaDiscovery
对服务进行遍历,如果状态为UP,转换成DiscoveryEnabledServer对象,组织成list返回。
DiscoveryEnabledNIWSServerList从eureka中拿到server列表后,继续通过DomainExtractingServerList的setZone进行处理,加入了一些必要属性
更新服务待续,没看明白
ZoneAwareLoadBalancer继承自DynamicServerListLoadBalancer并重写了setServerListForZones
个性化配置
ribbon的使用
spring cloud ribbon 是一个基于http和TCP客户度负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
负载均衡有两种,一般是服务器负载均衡,分为硬件负载均衡和软件负载均衡. 硬件负载均衡是用于服务器节点之间的负载均衡设备 软件负载均衡是通过在服务器上安装一些负载均衡的软件,来完成一些请求分发的工作,例如我们现在用的Nginx
创建一个spring boot的工程,然后勾选上
添加配置文件
在启动类上添加
我们需要使用对象RestTemplate。该对象会使用Ribbon的自动化配置,同时通过配置@LoadBalanced开启客户端负载均衡。
编写一个测试类,注入template
启动两个producer 可以在注册中心看到
?? getForEntity(String url, Class responseType,Object... urlVariables);
?? getForEntity(String url, Class responseType, Map urlVariables);
?? getForEntity(URI url, Class responseType)
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
RestTemplate restTemplate = new RestTemplate();
User result = restTemplate.getForObject(uri, User.class);
?? getForObject(String url, Class responseType, Object ... urlVariables)
?? getForObject(String url, Class responseType, Map urlVariables)
?? getForObject(URI url, Class responseType)
?? 第一种:postForEntity函数。
postForEntity函数也实现了三种不同的重载方法。
?? postForEntity(String url, Object request, Class responseType, Object... uriVariables)
?? postForEntity(String url, Object request, Class responseType, Map uriVariables)
?? postForEntity(URI url, Object request, Class responseType)
?? 第二种:postForObject函数。
postForObject函数也实现了三种不同的重载方法:
?? postForObject(String url, Object request, Class responseType, Object... uriVariables)
?? postForObject(String url, Object request, Class responseType, Map uriVariables)
?? postForObject(URI url, Object request, Class responseType)
?? 第三种:postForLocation函数。
?? postForLocation(String url, Object request, Object... uriVariables)
?? postForLocation(String url, Object request, Map uriVariables)
?? postForLocation(URI url, Object request)
由于postForLocation函数会返回新资源的URI,该URI就相当于指定了返回类型,所以此方法实现的POST请求不需要像postForEntity和postForObject那样指定responseType。其他的参数用法相同。
参考文章: https://www.jianshu.com/p/1bd66db5dc46
SpringCloud无介绍快使用,Ribbon负载均衡工具与OpenFeign的使用(十五)
@ TOC
从零开始学springcloud微服务项目
注意事项:
1 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具
2 集中式LB
3 进程内LB
4 Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别
5 Ribbon在工作时分成两步
6 前面几个篇章就是使用了Ribbon负载均衡,RestTemplate+@LoadBalanced实现负载均衡,使用依赖包含在Eureka-client中
1 OpenFeign集成了Ribbon
更改application文件,添加超时连接控制和日志增强
更改启动类
添加openFeign的日志打印配置
更改controller
添加feign调用
6 整体目录结构
7 postman测试: http://localhost/consumer/feign/get/1
SpringCloud无介绍快使用,Seata处理分布式事务(二十五)
SpringCloud无介绍快使用,sentinel服务熔断功能(二十四)
SpringCloud无介绍快使用,sentinel注解@SentinelResource的基本使用(二十三)
SpringCloud无介绍快使用,sentinel热点key限流与系统规则的基本使用(二十二)
SpringCloud无介绍快使用,sentinel熔断降级和限流的基本使用(二十一)
SpringCloud无介绍快使用,Nacos集群和Nginx代理(二十)
SpringCloud无介绍快使用,nacos配置中心的基本使用(十九)
SpringCloud无介绍快使用,nacos注册中心的基本使用(十八)
SpringCloud无介绍快使用,gateway通过微服务名实现动态路由(十七)
SpringCloud无介绍快使用,gateway的基本使用(十六)
SpringCloud无介绍快使用,Ribbon负载均衡工具与OpenFeign的使用(十五)
SpringCloud无介绍快使用,使用Zookeeper替换Eureka服务注册与发现(十四)
SpringCloud无介绍快使用,服务发现Discovery和Eureka自我保护(十三)
SpringCloud无介绍快使用,集群cloud-provider-payment8002搭建(十二)
SpringCloud无介绍快使用,集群Eureka服务注册中心cloud-eureka-server7002搭建(十一)
SpringCloud无介绍快使用,单机Eureka服务注册中心cloud-eureka-server7001搭建(十)
SpringCloud无介绍快使用,新建cloud-api-commons公共模块module(九)
SpringCloud无介绍快使用,新建子module消费者订单模块(八)
SpringCloud无介绍快使用,热部署devtools配置(七)
SpringCloud无介绍快使用,子module提供者支付微服务业务开发(六)
SpringCloud无介绍快使用,新建子module提供者支付微服务yml整合和新建启动类(五)
SpringCloud无介绍快使用,新建子module提供者支付微服务pom整合(四)
SpringCloud无介绍快使用,springcloud父工程pom文件整理(三)
SpringCloud无介绍快使用,IDEA新建springcloud父工程(二)
SpringCloud无介绍快使用,与Spingboot之间的兼容版本选择(一)
作为程序员第 182 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha ...
Ribbon 简介
Ribbon 是 NetFlix 公司退出的开源软件,是基于 HTTP 和 TCP 协议的,其主要功能是实现客户端的负载均衡算法。 Spring Cloud 中Ribbon是基于NetFlix公司的 Ribbon实现的。它不需要单独部署,但是却存在于整个微服务中。OpenFegin 也是基础Ribbon实现的。
所有的项目都会注册到 Eureka 中,Eureka 允许不同项目的 spring.application.name 相同。当相同时会认为是这些项目是一个集群,所以同一个项目部署多次都是设置应用程序名相同。
Application Client 会从 Eureka 中根据 spring.application.name 加载 Application Service 的列表。根据设定的负载均衡算法,从列表中取出一个 URL,到此 Ribbon 的事情结束。 剩下的事情由程序员自己进行技术选型,选择一个 HTTP 协议工具,通过这个 URL 调用 Application Service。
也叫做:服务端负载均衡。
将负载均衡逻辑集成到客户端组件中,客户端组件从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择一个合适的服务端发起请求。Ribbon 就是一个进程内负载均衡的实现。 也叫做:客户端负载均衡。
微服务架构把项目查分成多个项目,一定会出现一个项目调用另外一个项目的情况。 再加上 Eureka 支持多项目同项目名(spring.application.name)所以这个时候就可以使用到 Ribbon。
项目B 和项目C 实际上是同一个项目,项目 A 调用项目 B 和项目 C ,那么 Ribbon 应该配置在项目 A 中(Application Client 中)。
Ribbon与Nginx的区别
我们知道负载均衡有硬件负载均衡与软件的负载均衡方案
硬件负载均衡:比如 F5、深信服、Array 等; 软件负载均衡:比如 Nginx、LVS、HAProxy 等; 硬件负载均衡或是软件负载均衡,他们都会维护一个可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如轮询、权重、 最小连接数等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,是一个基于HTTP和TCP的客户端负载均衡工具。
Ribbon与Nginx的区别
Nginx是基于服务端的负载均衡,客户端所有请求统一交给 nginx,由 nginx 进行实现负载均衡请求转发,Nginx保持服务清单的同时,也负责负载均衡算法
Ribbon是从 eureka 注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现轮询负载均衡策略,Ribbon不负责出来服务清单,
Ribbon提供七种负载均衡策略
由于Spring Cloud Ribbon的封装, 我们在微服务架构中使用客户端负载均衡调用非常简单, 只需要如下两步:
在SpringCloud中 Feign中集成了Ribbon,会自动使用负载均衡。
fallback是自定义异常熔断类,声明后的接口出现异常时,会自动执行服务降级
SpringCloud系列-2Ribbon简介与应用
负载均衡:建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡说白了其实就是伴随着微服务架构的诞生的产物;过去的单体架构,前端页面发起请求,然后后台接收请求直接处理,这个时候不存在什么负载均衡;但是随着单体架构向微服务架构的演变,每个后台服务可能会部署在多台服务器上面,这个时候页面请求进来,到底该由哪台服务器进行处理呢?所以得有一个选择,而这个过程就是负载均衡;同时选择的方案有很多种,例如随机挑选一台或者一台一台轮着来,这就是负载均衡算法。
也可以通过例子来帮助自己记忆,就好比古代皇帝翻牌子,最开始皇帝只有一个妃子,那不存在翻牌子这回事,再怎么翻也只能是这一个妃子侍寝。但是随着妃子多了,就得有选择了,不能同时让所有妃子一起侍寝。
工作原理图如下:
HTTP重定向服务器是一台普通的应用服务器,其唯一个功能就是根据用户的HTTP请求计算出一台真实的服务器地址,并将该服务器地址写入HTTP重定向响应中返回给用户浏览器。用户浏览器在获取到响应之后,根据返回的信息,重新发送一个请求到真实的服务器上。DNS服务器解析到IP地址为192.168.8.74,即HTTP重定向服务器的IP地址。重定向服务器计根据某种负载均衡算法算出真实的服务器地址为192.168.8.77并返回给用户浏览器,用户浏览器得到返回后重新对192.168.8.77发起了请求,最后完成访问。
这种负载均衡方案的优点是比较简单,缺点是浏览器需要两次请求服务器才能完成一次访问,性能较差;同时,重定向服务器本身的处理能力有可能成为瓶颈,整个集群的伸缩性规模有限;因此实践中很少使用这种负载均衡方案来部署。
DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。人们在通过浏览器访问网站时只需要记住网站的域名即可,而不需要记住那些不太容易理解的IP地址。在DNS系统中有一个比较重要的的资源类型叫做主机记录也称为A记录,A记录是用于名称解析的重要记录,它将特定的主机名映射到对应主机的IP地址上。如果你有一个自己的域名,那么要想别人能访问到你的网站,你需要到特定的DNS解析服务商的服务器上填写A记录,过一段时间后,别人就能通过你的域名访问你的网站了。DNS除了能解析域名之外还具有负载均衡的功能,下面是利用DNS工作原理处理负载均衡的工作原理图:
由上图可以看出,在DNS服务器中应该配置了多个A记录,如: www.woshuaiqi.com IN A 192.168.8.75; www.woshuaiqi.com IN A 192.168.8.76; www.woshuaiqi.com IN A 192.168.8.77;
因此,每次域名解析请求都会根据对应的负载均衡算法计算出一个不同的IP地址并返回,这样A记录中配置多个服务器就可以构成一个集群,并可以实现负载均衡。上图中,用户请求www.woshuaiqi.com,DNS根据A记录和负载均衡算法计算得到一个IP地址192.168.8.77,并返回给浏览器,浏览器根据该IP地址,访问真实的物理服务器192.168.8.77。所有这些操作对用户来说都是透明的,用户可能只知道www.woshuaiqi.com这个域名。
DNS域名解析负载均衡有如下优点:
同时,DNS域名解析也存在如下缺点:
请求过程:
用户发来的请求都首先要经过反向代理服务器,服务器根据用户的请求要么直接将结果返回给用户,要么将请求交给后端服务器处理,再返回给用户。
反向代理负载均衡
优点:
缺点:
代码实现
由于不同的服务器配置不同,因此它们处理请求的能力也不同,给配置高的服务器配置相对较高的权重,让其处理更多的请求,给配置较低的机器配置较低的权重减轻期负载压力。加权轮询可以较好地解决这个问题。
1.思路
根据权重的大小让其获得相应被轮询到的机会。
可以根据权重我们在内存中创建一个这样的数组{s1,s2,s2,s3,s3,s3},然后再按照轮询的方式选择相应的服务器。
2.缺点:请求被分配到三台服务器上机会不够平滑。前3次请求都不会落在server3上。
Nginx实现了一种平滑的加权轮询算法,可以将请求平滑(均匀)的分配到各个节点上。
代码实现
代码实现
思路:这里我们是利用区间的思想,通过一个小于在此区间范围内的一个随机数,选中对应的区间(服务器),区间越大被选中的概率就越大。
已知:
s1:[0,1] s2:(1,3] s3 (3,6]
代码实现
代码实现
REST(Representational State Transfer)表象化状态转变(表述性状态转变),基于HTTP、URI、XML、JSON等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是Web服务的一种新的架构风格(一种思想)。
符合上述REST原则的架构方式称为RESTful
在Restful之前的操作: http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据 http://127.0.0.1/user/save POST 新增用户 http://127.0.0.1/user/update POST 修改用户信息 http://127.0.0.1/user/delete/1 GET/POST 删除用户信息
RESTful用法: http://127.0.0.1/user/1 GET 根据用户id查询用户数据 http://127.0.0.1/user POST 新增用户 http://127.0.0.1/user PUT 修改用户信息 http://127.0.0.1/user DELETE 删除用户信息
之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了query,新增的时候用了save,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.
幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。
安全性:对该REST接口访问,不会使用服务器端资源的状态发生改变。
SpringMVC原生态的支持了REST风格的架构设计
所涉及到的注解:
---@RequestMapping ---@PathVariable ---@ResponseBody
传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。
定义一个简单的restful接口
使用RestTemplate访问该服务
从这个例子可以看出,使用restTemplate访问restful接口非常的 简单粗暴无脑 。(url, requestMap, ResponseBean.class)这三个参数分别代表 请求地址、请求参数、HTTP响应转换被转换成的对象类型。
RestTemplate方法的名称遵循命名约定,第一部分指出正在调用什么HTTP方法,第二部分指示返回的内容。本例中调用了restTemplate.postForObject方法,post指调用了HTTP的post方法,Object指将HTTP响应转换为您选择的 对象类型 。
RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。
实际上,由于Post 操作的非幂等性,它几乎可以代替其他的CRUD操作.
目前主流的负载方案分为以下两种:
Ribbon 是一个基于 HTTP和TCP的客户端负载均衡工具。通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。
Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的(https://github.com/Netflix/ribbon)。
Ribbon主要提供:
Ribbon模块介绍:
与Nginx的对比
应用场景的区别:
1.先创建两个服务,用于负载均衡
Server 1 和Server2 的端口号要不同,不然起不来
Server 1接口如下:
Server 2接口如下:
启动类都是一样的,如下:
2.创建一个调用方来请求这个接口
引依赖包
配置启动类,并注入 RestTemplate
配置一下 application.properties,如下:
3.验证
再创建一个 测试方法来验证是否生效,放在test 目录下面,代码如下:
先启动 两个server ,然后在 测试 测试类 ,结果如下:
从结果可以看出实现了负载均衡,默认是 轮询策略,Client1和 clien2 依次调用。
Ribbon 中有两种和时间相关的设置,分别是请求连接的超时时间和请求处理的超时时间,设置规则如下:
Ribbon可以通过下面的配置项,来限制httpclient连接池的最大连接数量、以及针对不同host的最大连接数量。
负载均衡的核心,是通过负载均衡算法来实现对目标服务请求的分发。Ribbion中默认提供了7种负载均衡算法:
验证方法:
1.在BaseLoadBalancer.chooseServer()方法中加断点
2.在RandomRule.choose()方法增加断点,观察请求是否进入。
自定义负载均衡的实现主要分几个步骤:
ILoadBalancer 接口实现类做了以下的一些事情:
修改application.properties文件
在ribbon负载均衡器中,提供了ping机制,每隔一段时间,就会去ping服务器,由 com.netflix.loadbalancer.IPing 接口去实现。
单独使用ribbon,不会激活ping机制,默认采用DummyPing(在RibbonClientConfiguration中实例化),isAlive()方法直接返回true。
ribbon和eureka集成,默认采用NIWSDiscoveryPing(在EurekaRibbonClientConfiguration中实例化的),只有服务器列表的实例状态为up的时候才会为Alive。
IPing中默认内置了一些实现方法如下。
在网络通信中,有可能会存在由网络问题或者目标服务异常导致通信失败,这种情况下我们一般会做容错设计,也就是再次发起请求进行重试。
Ribbon提供了一种重试的负载策略:RetryRule,可以通过下面这个配置项来实现
由于在单独使用Ribbon的机制下,并没有开启Ping机制,所以所有服务默认是认为正常的,则这里并不会发起重试。如果需要演示重试机制,需要增加PING的判断。
1.引入依赖包
2.创建一个心跳检查的类
3.修改mall-portal中application.properties文件,添加自定义心跳检查实现,以及心跳检查间隔时间。
4.在goods-service这个模块中,增加一个心跳检查的接口
5.测试服务启动+停止,对于请求的影响变化。
LoadBalancer 是Spring Cloud自研的组件,支持WebFlux。
由于Ribbon停止更新进入维护状态,所以Spring Cloud不得不研发一套新的Loadbalancer机制进行替代。
1.引入Loadbalancer相关jar包
2.定义一个配置类,这个配置类通过硬编码的方式写死了goods-service这个服务的实例列表,代码如下
3.创建一个配置类,注入一个LoadBalancerClient
4.修改测试类
5.为了更好的看到效果,修改goods-service模块,打印每个服务的端口号码。