本篇文章小编给大家分享一下SpringCloud Netflix Ribbon代码解析,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
首先会介绍Ribbon 相关的配置和实例的初始化过程,然后讲解Ribbon 是如何与OpenFeign 集成的,接着讲解负载均衡器LoadBalancerCp ent , 最后依次讲解ILoadB alancer的实现和负载均衡策略Rule 的实现。
配置和实例初始化
@RibbonCpent 注解可以声明Ribbon 客户端,设置Ribbon 客户端的名称和配置类,configuration 属性可以指定@Configuration 的配置类,进行Ribbon 相关的配置。@RibbonCpent还会导入( import ) RibbonCpentConfigurationRegistrar 类来动态注册Ribbon 相关的BeanDefinition。
RibbonCpentConfigurationRegistrar 是ImportBeanDefinitionRegistrar 的实现类,ImportBeanDefinitionRegistrar 是Spring 动态注册BeanDefinition 的接口, 可以用来注册Ribbon 所需的BeanD的iition , 比如说Ribbon客户端实例( Ribbon Cpent ) lmportBeanDefinitionRegistrar的registerBeanDefinitions 方法可以注册Ribbon 客户端的配置类, 也就是@RibbonCpent 的configuration 属性值
与OpenFeign 的集成
FeignCJientFactoryBean 是创造FeignCpent 的工厂
类,在其getObject 方法中有一个分支判断,当请求URL 不为空时, 就会生成一个具有负载均衡的FeignCpent 。在这个过程中, OpenFeign 就默认引入了Ribbon 的负载均衡实现.
LoadBalancerFeignCpent#execute 方法会将普通的Request 对象转化为RibbonRequest , 并使用FeignLoadBalancer 实例来发送RibbonRequest。execute 方法会首先将Request 的URL转化为对应的服务名称,然后构造出RibbonRequest 对象,接着调用lbCpent 方法来生成FeignLoadBalancer 实例,最后调用FeignLoadBalancer 实例的executeWithLoadBalancer 方法来处理网络请求。
//LoadBalancerFeignClient java public Response execute(Reqest reqi且est, Request .Options options) throws 工OException { try { // :负载均衡时, host 就是需要调用的服务的名称 URI asurn= URI . create(request.url()) ; String clientName = asur. getHost(); URI ur 工WithoutHost = cleanUrl(reqi且est . url(), cl 工entName) ; //构造RibbonRequest,delegate 一般就是真正发送网络请求的客户端,比如说OkHttpClient 和ApacheClient Fe 工gnLoadBalancer . R 工bbonRequest ribbonRequest = new FeignLoadBalancer . RibbonRequest( this . delegate , re 守uest , ur 工WithoutHost) ; IClientConfig requestConfig = getClientConfig(options, clientName) ; //executeWithLoadBalancer是进行负载均衡的关键 return lbClient(clientName) . executeWithLoadBalancer(ribbonRequest , requestConfig) . toResponse () ; catch (ClientException e) { IOException io = findIOException(e) ; if ( io ! = null) { throw io; throw new RuntimeException(e) ; private FeignLoadBalancer lbCl 工ent(Str 工ng cl 工entName) { //调用CachingSpringLoadBalancerFactory 类的create方法。 return this . lbClientFactory . create(clientName) ;
lbCpentFactory 的参数是CachingSpringLoadBalancerFactory 的实例, 它是带有缓存机制的FeignLoadBalancer 的工厂类。
create 方法的cpentName 参数是指HTTP 请求对应的服务端名称, 它会首先使用这个名称去缓存中查找是否已经存在对应的实例。如果没有, 再根据系统是否支持请求重试来创建出不同的F eignLoadBalancer 实例, 最后将该实例存储到缓存中.
FeignLoadBalancer 是OpenFeign 在不需要重试机制的情况下默认的负载均衡实现。它的execute 方法的实现很简单,使用RibbonRequest 对象的客户端来发送网络请求,然后 将Response 包装成RibbonResponse 进行返回。RibbonRequest 的request 方法返回的对象就是构造RibbonRequest 对象时传入的delegate 参数。该参数是Cpent 接口的实例, Cpent接口是OpenFeign 真正发送网络请求的客户端, 比如说OkHttpCpent 和ApacheCpent 。FeignLoadBalancer 的execute 方法如下所示:
//Fe i gnLoadBalancer. ] ava public RibbonResponse execute(RibbonRequest request , IClientConfig configOverride) throws IOException { Request.Options options ; if (configOverride ! = null) { RibbonPropert 工es override = RibbonPropertes . from(configOverride); options = new Request.Options( else { override . connectTimeout(th 工s . connect Timeout), override . readTimeout(this . readT 工meout)); options = new Request . Options(th 工s.connectTimeout, this readTimeout); Response response = request . client() . execute(request . toReqest(), options) ; return new RibbonResponse(request . getUri() , response) ;
FeignLoadBalancer 是AbstractLoadBalancerAwareC!ient 的子类,其executeWithLoadBalance方法会首先创建一个LoadBalancerCommand 实例,然后在该实例的submit 方法的回调中调用子类的execute方法
其中, buildLoadB a lan cerCommand 方法使用了LoadBalancerCommand.Builder 来创建LoadBalancerCornmand 实例,并将AbstractLoadBalancerAwareC!ient 作LoadBalancerContext接口的实例设置给LoadBalancerCommand 实例
LoadBalancerContext 的getServerFromLoadBalancer 方法调用了ILoadBalancer 的chooseServer方法,从而完成了负载均衡中服务器的选择。
负载均衡器LoadBalancerCpent
LoadBalancerCpent是Ribbon 项目的核心类之一,可以在RestTemplate 发送网络请求时替代RestTemplate 进行网络调用
LoadBalancerCpent 接口继承了ServicelnstanceChooser 接口,其choose 方法可以从服务器列表中依据负载均衡策略选出一个服务器实例
RibbonLoadBalancerCpent 是LoadBalancerCpent 的实现类之一, 它的execute 方法会首先使用ILoadBa lancer 来选择服务器实例( Server ),然后将该服务器实例封装成RibbonServer 对象, 最后再调用LoadBalancerRequest 的apply 方法进行网络请求的处理。
ILoadBalancer
ILoadBalancer 是Ribbon 的关键类之二, 它是定义负载均衡操作过程的接口。Ribbon通过SpringCpentFactory 工厂类的getLoadBalancer 方法可以获取ILoadBalancer 实例。根据Ribbon 的组件实例化机制, ILoadBalnacer 实例是在RibbonAutoConfiguration 中被创建生成的。
SpringCpentFactory 中的实例都是RibbonCpentConfiguration 或者自定义C onfiguration配置类创建的Bean 实例。RibbonCpentConfiguration 还创建了Rule 、IPing 和S e rver pst
等相关组件的实例。使用者可以通过自定义配置类给出上述几个组件的不同实例。
负载均衡策略实现
lRule 是定义Ribbon 负载均衡策略的接口,你可以通过实现该接口来自定义自己的负载均衡策略, Ribbon CpentConfiguration 配置类则会给出!Rule 的默认实例,Rule 接口的choose 方法就是从一堆服务器中根据一定规则选出一个服务器。Rule 有很多默认的实现类,这些实现类根据不同的算法和逻辑来进行负载均衡。
在大多数情况下, 这些默认的实现类是可以满足需求的,如果有特殊需求,可以自己实现。Ribbon 内置的Rule 子类如下所示。
BestAvailableRule :选择最小请求数的服务器。
CpentConfigEnabledRoundRobinRule :使用RandomRobinRule 随机选择一个服务器。
RoundRobinRul e :以RandonRobin 方法轮询选择服务器。
RetryRule : 在选定的负载均衡策略上添加重试机制。
WeightedResponseTimeRule :根据响应时间去计算一个权重( we ight ) ,响应时间越
长,权重越低,权重越低的服务器,被选择的可能性就越低。
ZoneAvoidanceRule :根据服务器所属的服务区的整体运行状况来轮询选择。