安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

Ribbon源码2Ribbon工作流程

8月20日 斩情道投稿
  0。环境nacos版本:1。4。1SpringCloud:Hoxton。SR9SpringBoot:2。4。4SpringCloudalibaba:2。2。5。RELEASESpringCloudopenFeign2。2。2。RELEASE
  测试代码:github。comhsfxuebaos1。Ribbon的工作流程
  我们知道,微服务在启动成功之后,默认30s次会从注册中心拉取服务注册表到本地缓存起来,而我们使用Ribbon时是通过RestTemplate发起请求,URL以:http:userserveruser。。。服务名方式去调用服务,其实Ribbon干的事情就是根据URL中的服务名去本地的服务注册表中查找服务名对应的服务实例(一个或多个),然后通过负载均衡算法选择其中一个服务后,发起Http请求,那接下来我们就来看一下Ribbon的底层到底是怎么工作的2。Ribbon配合RestTemplate使用
  首选需要定义RestTemplateSpringBootApplicationEnableEurekaClientpublicclassOrderServerApplication1030{配置一个RestTemplate,http客户端,支持Rest风格LoadBalanced:负载均衡注册,让RestTmplate可以实现负载均衡请求这个标签标记RestTemplate可以使用LoadBalancerClient进行负载均衡BeanLoadBalancedpublicRestTemplaterestTemplate(){returnnewRestTemplate();}省略。。。}复制代码
  调用服务的是否使用服务名调用:RestControllerpublicclassOrderController{需要配置成BeanAutowiredprivateRestTemplaterestT浏览器调用该方法RequestMapping(valueorder{id},methodRequestMethod。GET)publicUsergetById(PathVariable(id)Longid){发送http请求调用user的服务,获取user对象:RestTemplateuser的ip,user的端口,user的Controller路径Stringurlhttp:localhost:1020Stringurlhttp:发送http请求returnrestTemplate。getForObject(url,User。class);}}复制代码
  被LoadBalanced标记的RestTemplate可以使用LoadBalancerClient负载均衡客户端实现负载均衡,我们在使用RestTemplate发起请求的时候需要跟上服务名的方式http:userserveruser3。LoadBalancerClient负载均衡客户端
  我们从LoadBalanced入手,先看一下LoadBalancerClient它的源码。注解标记RestTemplate可以使用LoadBalancerClient负载均衡客户端AnnotationtomarkaRestTemplatebeantobeconfiguredtouseaLoadBalancerClientauthorSpencerGibbTarget({ElementType。FIELD,ElementType。PARAMETER,ElementType。METHOD})Retention(RetentionPolicy。RUNTIME)DocumentedInheritedQualifierpublicinterfaceLoadBalanced{}复制代码
  这个注解LoadBalanced的作用在注释上说得非常清楚,就是标记RestTemplate可以使用使用LoadBalancerClient来实现负载均衡,LoadBalancerClient就是Ribbon实现负载均衡的一个客户端,它在springcloudcommons包下,我们可以直接看LoadBalancerClient的源码:客户端负载均衡RepresentsaclientsideloadbalancerauthorSpencerGibbpublicinterfaceLoadBalancerClientextendsServiceInstanceChooser{执行请求,会根据serviceId使用负载均衡查找服务使用负载均衡器执行指定服务executerequestusingaServiceInstancefromtheLoadBalancerforthespecifiedservice服务Id服务ID来查找负载平衡器paramserviceIdtheserviceidtolookuptheLoadBalancerparamrequestallowsimplementationstoexecutepreandpostactionssuchasincrementingmetrics返回选择的服务returntheresultoftheLoadBalancerRequestcallbackontheselectedServiceInstanceTTexecute(StringserviceId,LoadBalancerRequestTrequest)throwsIOE执行请求,这个方法多了一个参数ServiceInstance,即请求指定的服务executerequestusingaServiceInstancefromtheLoadBalancerforthespecifiedserviceparamserviceIdtheserviceidtolookuptheLoadBalancerparamserviceInstancetheservicetoexecutetherequesttoparamrequestallowsimplementationstoexecutepreandpostactionssuchasincrementingmetricsreturntheresultoftheLoadBalancerRequestcallbackontheselectedServiceInstanceTTexecute(StringserviceId,ServiceInstanceserviceInstance,LoadBalancerRequestTrequest)throwsIOE重构URL,把http:myservicepathtoservice重构成http:ip:端口pathtoserviceCreateaproperURIwitharealhostandportforsystemstoutilize。SomesystemsuseaURIwiththelogicalserivcenameasthehost,suchashttp:myservicepathtoservice。Thiswillreplacetheservicenamewiththehost:portfromtheServiceInstance。paraminstanceparamoriginalaURIwiththehostasalogicalservicenamereturnareconstructedURIURIreconstructURI(ServiceInstanceinstance,URIoriginal);}复制代码
  LoadBalancerClient接口三个方法,excute()为执行请求,reconstructURI()用来重构url,它实现了ServiceInstanceChooser接口,这个接口的作用是用来选择服务的,看下源码通过使用负载平衡器,选择一个服务器发送请求。Implementedbyclasseswhichusealoadbalancertochooseaservertosendarequestto。authorRyanBaxterpublicinterfaceServiceInstanceChooser{从LoadBalancer中为指定服务选择一个ServiceInstanceChooseaServiceInstancefromtheLoadBalancerforthespecifiedservice根据服务id去LoadBalancer查找服务paramserviceIdtheserviceidtolookuptheLoadBalancer返回查找到的服务实例ServiceInstancereturnaServiceInstancethatmatchestheserviceIdServiceInstancechoose(StringserviceId);}复制代码
  提供了一个choose方法,根据服务IDserviceId查找一个ServiceInstance服务实例,这里的serviceId其实就是http:userserverurl中带的服务名。
  LoadBalancerClient还有一个默认实现类RibbonLoadBalancerClient,这个实现是针对Ribbon的客户端负载均衡,继承关系如下:
  RibbonLoadBalancerClient是一个非常核心的类,最终的负载均衡的请求处理由它来执行,源码如下:publicclassRibbonLoadBalancerClientimplementsLoadBalancerClient{privateSpringClientFactoryclientFpublicRibbonLoadBalancerClient(SpringClientFactoryclientFactory){this。clientFactoryclientF}重构URL,找到服务之后,把http:服务名格式重构成http:ip:port格式OverridepublicURIreconstructURI(ServiceInstanceinstance,URIoriginal){Assert。notNull(instance,instancecannotbenull);StringserviceIdinstance。getServiceId();RibbonLoadBalancerContextcontextthis。clientFactory。getLoadBalancerContext(serviceId);URISif(instanceinstanceofRibbonServer){RibbonServerribbonServer(RibbonServer)serverribbonServer。getServer();uriupdateToSecureConnectionIfNeeded(original,ribbonServer);}else{servernewServer(instance。getScheme(),instance。getHost(),instance。getPort());IClientConfigclientConfigclientFactory。getClientConfig(serviceId);ServerIntrospectorserverIntrospectorserverIntrospector(serviceId);uriupdateToSecureConnectionIfNeeded(original,clientConfig,serverIntrospector,server);}returncontext。reconstructURIWithServer(server,uri);}根据服务名,查找服务实例,选择一个返回ServiceInstanceOverridepublicServiceInstancechoose(StringserviceId){查找服务ServerservergetServer(serviceId);if(servernull){}returnnewRibbonServer(serviceId,server,isSecure(server,serviceId),serverIntrospector(serviceId)。getMetadata(server));}执行请求OverridepublicTTexecute(StringserviceId,LoadBalancerRequestTrequest)throwsIOException{获取负载均衡器〔重要〕ILoadBalancerloadBalancergetLoadBalancer(serviceId);选择服务,使用负载均衡器,根据服务的ID,选择一个服务ServerservergetServer(loadBalancer);if(servernull){thrownewIllegalStateException(NoinstancesavailableforserviceId);}选择的服务封装成一个RibbonServer:RibbonServerimplementsServiceInstanceRibbonServerribbonServernewRibbonServer(serviceId,server,isSecure(server,serviceId),serverIntrospector(serviceId)。getMetadata(server));执行请求调用服务returnexecute(serviceId,ribbonServer,request);}执行请求调用服务OverridepublicTTexecute(StringserviceId,ServiceInstanceserviceInstance,LoadBalancerRequestTrequest)throwsIOException{Sif(serviceInstanceinstanceofRibbonServer){server((RibbonServer)serviceInstance)。getServer();}if(servernull){thrownewIllegalStateException(NoinstancesavailableforserviceId);}RibbonLoadBalancerContextcontextthis。clientFactory。getLoadBalancerContext(serviceId);RibbonStatsRecorderstatsRecordernewRibbonStatsRecorder(context,server);try{使用LoadBalancerRequest向服务发请求TreturnValrequest。apply(serviceInstance);statsRecorder。recordStats(returnVal);returnreturnV}catchIOExceptionandrethrowsoRestTemplatebehavescorrectlycatch(IOExceptionex){statsRecorder。recordStats(ex);}catch(Exceptionex){statsRecorder。recordStats(ex);ReflectionUtils。rethrowRuntimeException(ex);}}privateServerIntrospectorserverIntrospector(StringserviceId){ServerIntrospectorserverIntrospectorthis。clientFactory。getInstance(serviceId,ServerIntrospector。class);if(serverIntrospectornull){serverIntrospectornewDefaultServerIntrospector();}returnserverI}是否是https请求privatebooleanisSecure(Serverserver,StringserviceId){IClientConfigconfigthis。clientFactory。getClientConfig(serviceId);ServerIntrospectorserverIntrospectorserverIntrospector(serviceId);returnRibbonUtils。isSecure(config,serverIntrospector,server);}根据服务ID选择服务protectedServergetServer(StringserviceId){returngetServer(getLoadBalancer(serviceId));}负载均衡器选择服务protectedServergetServer(ILoadBalancerloadBalancer){if(loadBalancernull){}returnloadBalancer。chooseServer(default);TODO:betterhandlingofkey}根据服务id得到负载均衡器protectedILoadBalancergetLoadBalancer(StringserviceId){returnthis。clientFactory。getLoadBalancer(serviceId);}。。。省略。。。复制代码
  解释一下:
  这里的ServiceInstancechoose(StringserviceId)方法的作用是根据ServideId选择一个服务,底层实现是通过LoadBalancer。chooseServer负载均衡器LoadBalancer来完成的服务的选择的
  选择到服务之后调用execute向选择到的服务发起请求,通过LoadBalancerRequest来完成其请求。4。RestTemplate的执行流程
  RestTmplate发请求时地址http:userserveruserid中userserver是当前服务需要调用的目标服务的服务名,那么Ribbon到底是如何实现负载均衡调用的呢?我们可以从这里跟踪一下RestTemplate的执行流程:publicclassRestTemplateextendsInterceptingHttpAccessorimplementsRestOperations{。。。省略。。。NullableprotectedTTdoExecute(URIurl,NullableHttpMethodmethod,NullableRequestCallbackrequestCallback,NullableResponseExtractorTresponseExtractor)throwsRestClientException{Assert。notNull(url,URIisrequired);Assert。notNull(method,HttpMethodisrequired);ClientHttpRObjectvar14;try{创建请求对象,使用SimpleClientHttpRequestFactory创建ClientHttpRequestClientHttpRequestrequestthis。createRequest(url,method);if(requestCallback!null){设置header和bodyrequestCallback。doWithRequest(request);}responserequest。execute();this。handleResponse(url,method,response);var14responseExtractor!null?responseExtractor。extractData(response):}catch(IOExceptionvar12){Stringresourceurl。toString();Stringqueryurl。getRawQuery();resourcequery!null?resource。substring(0,resource。indexOf(63)):thrownewResourceAccessException(IOerroronmethod。name()requestforresource:var12。getMessage(),var12);}finally{if(response!null){response。close();}}returnvar14;}复制代码
  请求来到RestTemplatedoExecute方法,首选是通过使用SimpleClientHttpRequestFactory根据url和method创建ClientHttpRequest请求对象,使用的实现是InterceptingClientHttpRequestFactory,然后使用responserequest。execute();去执行请求,一路跟踪,请求来到InterceptingClientHttpRequestexecuteInternal:classInterceptingClientHttpRequestextendsAbstractBufferingClientHttpRequest{headers请求头,bufferedOutput输出内容protectedfinalClientHttpResponseexecuteInternal(HttpHeadersheaders,byte〔〕bufferedOutput)throwsIOException{创建拦截器执行器InterceptingClientHttpRequest。InterceptingRequestExecutionrequestExecutionnewInterceptingClientHttpRequest。InterceptingRequestExecution();returnrequestExecution。execute(this,bufferedOutput);}复制代码
  这里通过InterceptingClientHttpRequest。InterceptingRequestExecution()拦截器执行器去执行请求,请求来到InterceptingClientHttpRequest。InterceptingRequestExecutionexecute:privateclassInterceptingRequestExecutionimplementsClientHttpRequestExecution{privatefinalIteratorClientHttpRequestIpublicInterceptingRequestExecution(){this。iteratorInterceptingClientHttpRequest。this。interceptors。iterator();}publicClientHttpResponseexecute(HttpRequestrequest,byte〔〕body)throwsIOException{if(this。iterator。hasNext()){〔重要〕这里取到的正是LoadBalancerInterceptorClientHttpRequestInterceptornextInterceptor(ClientHttpRequestInterceptor)this。iterator。next();returnnextInterceptor。intercept(request,body,this);}else{HttpMethodmethodrequest。getMethod();Assert。state(method!null,NostandardHTTPmethod);如果iterator中没有拦截器了,就创建一个ClientHttpRequest去执行请求ClientHttpRequestdelegateInterceptingClientHttpRequest。this。requestFactory。createRequest(request。getURI(),method);request。getHeaders()。forEach((key,value){delegate。getHeaders()。addAll(key,value);});if(body。length0){if(delegateinstanceofStreamingHttpOutputMessage){StreamingHttpOutputMessagestreamingOutputMessage(StreamingHttpOutputMessage)streamingOutputMessage。setBody((outputStream){StreamUtils。copy(body,outputStream);});}else{StreamUtils。copy(body,delegate。getBody());}}执行请求returndelegate。execute();}}}复制代码
  InterceptingRequestExecution中维护了一个I其中LoadBalancerInterceptor就在该集合中,所以请求来到LoadBalancerInterceptorintercept(request,body,this);方法负载均衡拦截器publicclassLoadBalancerInterceptorimplementsClientHttpRequestInterceptor{负载均衡客户端〔重要〕privateLoadBalancerClientloadB负载均衡请求创建工厂privateLoadBalancerRequestFactoryrequestF初始化publicLoadBalancerInterceptor(LoadBalancerClientloadBalancer,LoadBalancerRequestFactoryrequestFactory){this。loadBalancerloadBthis。requestFactoryrequestF}初始化publicLoadBalancerInterceptor(LoadBalancerClientloadBalancer){forbackwardscompatibilitythis(loadBalancer,newLoadBalancerRequestFactory(loadBalancer));}拦截器核心方法【重要】request请求对象body内容OverridepublicClientHttpResponseintercept(finalHttpRequestrequest,finalbyte〔〕body,finalClientHttpRequestExecutionexecution)throwsIOException{请求的URL,格式如:http:userserveruser1,userserver是服务名finalURIoriginalUrirequest。getURI();URL中的服务名StringserviceNameoriginalUri。getHost();Assert。state(serviceName!null,RequestURIdoesnotcontainavalidhostname:originalUri);通过requestFactory。createRequest(request,body,execution)创建LoadBalancerRequest然后调用负载均衡器执行请求,参数:服务名,LoadBalancerRequestreturnthis。loadBalancer。execute(serviceName,requestFactory。createRequest(request,body,execution));}}复制代码
  这里蛮重要的,请求调用了LoadBalancerInterceptorintercept负载均衡拦截器的拦截方法,获取到URL,从中获取到主机名即调用的服务名(Ribbon客户端服务名),然后使用LoadBalancerRequestFactory创建了LoadBalancerRequest请求对象,调用loadBalancerexecute负载均衡器执行请求5。ILoadBalancer选择服务(负载均衡)
  请求来到RibbonLoadBalancerClientexecute:OverridepublicTTexecute(StringserviceId,LoadBalancerRequestTrequest)throwsIOException{获取负载均衡器ILoadBalancerloadBalancergetLoadBalancer(serviceId);loadBalancer选择服务ServerservergetServer(loadBalancer);if(servernull){thrownewIllegalStateException(NoinstancesavailableforserviceId);}选择的服务封装成RibbonServerRibbonServerribbonServernewRibbonServer(serviceId,server,isSecure(server,serviceId),serverIntrospector(serviceId)。getMetadata(server));LoadBalancerRequest对服务执行请求returnexecute(serviceId,ribbonServer,request);}复制代码
  这里就蛮关键了:首选是通过服务名调用getLoadBalancer方法得到负载均衡器然后getServer(loadBalancer)是通过负载均衡器选择一个服务,底层会使用IRule的算法然后将服务封装成RibbonServer对象,交给LoadBalancerRequest去执行请求
  这里的负载均衡器默认会走ZoneAwareLoadBalancer,它是通过SpringClientFactory从Ribbon上下文对象中获取到的负载均衡器对象,关于这个我们在上一章讨论过publicclassRibbonLoadBalancerClientimplementsLoadBalancerClient{。。。省略。。。privateSpringClientFactoryclientFprotectedILoadBalancergetLoadBalancer(StringserviceId){returnthis。clientFactory。getLoadBalancer(serviceId);}复制代码
  而得到ILoadBalancer之后,调用getServer(loadBalancer)方法选择服务,我们跟踪一下publicclassRibbonLoadBalancerClientimplementsLoadBalancerClient{。。。省略。。。protectedServergetServer(ILoadBalancerloadBalancer){if(loadBalancernull){}ZoneAwareLoadBalancerchooseServerreturnloadBalancer。chooseServer(default);TODO:betterhandlingofkey}复制代码
  这里loadBalancer。chooseServer(default);请求来到ZoneAwareLoadBalancerchooseServer,源码如下:publicclassZoneAwareLoadBalancerTextendsServerextendsDynamicServerListLoadBalancerT{。。。省略。。。OverridepublicServerchooseServer(Objectkey){if(!ENABLED。get()getLoadBalancerStats()。getAvailableZones()。size()1){如果禁用了zone,或者自由一个zone会走这里logger。debug(Zoneawarelogicdisabledorthereisonlyonezone);returnsuper。chooseServer(key);}下面就是根据zone选择服务了,默认情况下不会走下面Stry{LoadBalancerStatslbStatsgetLoadBalancerStats();得到zone快照MapString,ZoneSnapshotzoneSnapshotZoneAvoidanceRule。createSnapshot(lbStats);logger。debug(Zonesnapshots:{},zoneSnapshot);if(triggeringLoadnull){triggeringLoadDynamicPropertyFactory。getInstance()。getDoubleProperty(ZoneAwareNIWSDiscoveryLoadBalancer。this。getName()。triggeringLoadPerServerThreshold,0。2d);}if(triggeringBlackoutPercentagenull){triggeringBlackoutPercentageDynamicPropertyFactory。getInstance()。getDoubleProperty(ZoneAwareNIWSDiscoveryLoadBalancer。this。getName()。avoidZoneWithBlackoutPercetage,0。99999d);}得到可用的zoneSetStringavailableZonesZoneAvoidanceRule。getAvailableZones(zoneSnapshot,triggeringLoad。get(),triggeringBlackoutPercentage。get());logger。debug(Availablezones:{},availableZones);if(availableZones!nullavailableZones。size()zoneSnapshot。keySet()。size()){随机选择区域StringzoneZoneAvoidanceRule。randomChooseZone(zoneSnapshot,availableZones);logger。debug(Zonechosen:{},zone);if(zone!null){BaseLoadBalancerzoneLoadBalancergetLoadBalancer(zone);选择服务serverzoneLoadBalancer。chooseServer(key);}}}catch(Exceptione){logger。error(Errorchoosingserverusingzoneawarelogicforloadbalancer{},name,e);}if(server!null){}else{logger。debug(Zoneavoidancelogicisnotinvoked。);returnsuper。chooseServer(key);}}复制代码
  这里做了一个判断,如果没有设置zone或者只有一个zone(默认),这里会调用returnsuper。chooseServer(key);通过父类的BaseLoadBalancerchooseServer方法选择服务,这也是默认的执行流程,代码走到了BaseLoadBalancerchooseServer方法中,源码如下publicclassBaseLoadBalancerextendsAbstractLoadBalancerimplementsPrimeConnections。PrimeConnectionListener,IClientConfigAware{publicServerchooseServer(Objectkey){if(counternull){创建一个计数器countercreateCounter();}计数器增加counter。increment();如果负载均衡规则为空,返回空if(rulenull){}else{try{〔重要〕调用了负载均衡器算法类的choose方法returnrule。choose(key);}catch(Exceptione){logger。warn(LoadBalancer〔{}〕:Errorchoosingserverforkey{},name,key,e);}}}复制代码
  在BaseLoadBalancerchooseServer方法中调用了IRulechoose方法进行服务的选择服务,IRule有很多是算法策略实现类,默认会走轮询算法,如果有定义负载均衡算法,这里rule。choose调用的就是定义的算法类。
  这里我打了个端点,跟踪了一下源码发现默认情况下会从BaseLoadBalancerchooseServer方法中调用PredicateBasedRulechoose,PredicateBasedRule本身是继承ClientConfigEnabledRoundRobinRule,也就是说PredicateBasedRule是使用的是轮询算法,同时它扩展了Predicate功能,即:提供了服务器过滤逻辑一个规则,提供了服务器过滤逻辑,具体使用的是AbstractServerPredicate实现过滤功能。过滤后,服务器从过滤列表中的循环方式返回。Arulewhichdelegatestheserverfilteringlogictoaninstanceof{linkAbstractServerPredicate}。Afterfiltering,aserverisreturnedfromfilteredlistinaroundrobinfashion。authorawangpublicabstractclassPredicateBasedRuleextendsClientConfigEnabledRoundRobinRule{抽象函数,返回AbstractServerPredicate,用来对服务做过滤的Methodthatprovidesaninstanceof{linkAbstractServerPredicate}tobeusedbythisclass。publicabstractAbstractServerPredicategetPredicate();Getaserverbycalling{linkAbstractServerPredicatechooseRandomlyAfterFiltering(java。util。List,Object)}。TheperformanceforthismethodisO(n)wherenisnumberofserverstobefiltered。OverridepublicServerchoose(Objectkey){得到负载均衡器ILoadBalancerlbgetLoadBalancer();通过AbstractServerPredicate的chooseRoundRobinAfterFiltering选出具体的服务实例AbstractServerPredicate的子类实现的Predicate逻辑来过滤一部分服务实例然后在以线性轮询的方式从过滤后的实例中选出一个OptionalServerservergetPredicate()。chooseRoundRobinAfterFiltering(lb。getAllServers(),key);if(server。isPresent()){returnserver。get();}else{}}}复制代码
  这里使用了AbstractServerPredicatechooseRoundRobinAfterFiltering来选择服务从lb。getAllServers()得到所有的服务作为参数,继续跟踪下去Chooseaserverinaroundrobinfashionafterthepredicatefiltersagivenlistofserversandloadbalancerkey。publicOptionalServerchooseRoundRobinAfterFiltering(ListServerservers,ObjectloadBalancerKey){得到合格的服务列表,主要根据zone做一个过滤ListServereligiblegetEligibleServers(servers,loadBalancerKey);if(eligible。size()0){没找到合格的服务returnOptional。absent();}以线性轮询的方式合格的服务列表获取一个实例incrementAndGetModulo方法会以轮询的方式计算一个下标值returnOptional。of(eligible。get(incrementAndGetModulo(eligible。size())));}。。。省略。。。引用于RoundRobinRule算法策略,轮询ReferencedfromRoundRobinRuleInspiredbytheimplementationof{linkAtomicIntegerincrementAndGet()}。parammoduloThemodulotoboundthevalueofthecounter。returnThenextvalue。增量和取模实现轮询privateintincrementAndGetModulo(intmodulo){for(;;){intcurrentnextIndex。get();intnext(current1)if(nextIndex。compareAndSet(current,next)currentmodulo)}}复制代码
  这里首先会通过zone过滤出可用的服务列表,然后使用轮询算法选择一个服务返回,到这里选择服务的流程调用6。LoadBalancerRequest执行服务
  代码继续回到RibbonLoadBalancerClientexecute,选择完服务之后,服务被封装成RibbonServer:OverridepublicTTexecute(StringserviceId,LoadBalancerRequestTrequest)throwsIOException{得到负载均衡器ILoadBalancerloadBalancergetLoadBalancer(serviceId);选择服务ServerservergetServer(loadBalancer);if(servernull){thrownewIllegalStateException(NoinstancesavailableforserviceId);}把server封装成RibbonServerRibbonServerribbonServernewRibbonServer(serviceId,server,isSecure(server,serviceId),serverIntrospector(serviceId)。getMetadata(server));执行服务调用returnexecute(serviceId,ribbonServer,request);}复制代码
  找到服务后,调用了execute方法执行后续请求OverridepublicTTexecute(StringserviceId,ServiceInstanceserviceInstance,LoadBalancerRequestTrequest)throwsIOException{Sif(serviceInstanceinstanceofRibbonServer){server((RibbonServer)serviceInstance)。getServer();}if(servernull){thrownewIllegalStateException(NoinstancesavailableforserviceId);}加载Ribbon负载均衡器上下文对象RibbonLoadBalancerContextcontextthis。clientFactory。getLoadBalancerContext(serviceId);RibbonStatsRecorderstatsRecordernewRibbonStatsRecorder(context,server);try{LoadBalancerRequest。apply执行请求TreturnValrequest。apply(serviceInstance);statsRecorder。recordStats(returnVal);returnreturnV}catchIOExceptionandrethrowsoRestTemplatebehavescorrectlycatch(IOExceptionex){statsRecorder。recordStats(ex);}catch(Exceptionex){statsRecorder。recordStats(ex);ReflectionUtils。rethrowRuntimeException(ex);}}复制代码
  这里调用LoadBalancerRequest。apply执行请求,后面还会调用LoadBalancerRequestFactorycreateRequest方法创建请求,调用ClientHttpRequestExecutionexecute执行,然后又会将请求委派给ClientHttpRequestexecute去执行,再往后面走就是创建HttpURLConnection链接对象发送请求了,我们就不继续跟下去了。7。总结
  纵观Ribbon的工作流程大致如下:初始化的时候创建好Ribbon的上下文,以及相关的组件,如ILoadBalancer,IConfig,IRule等等初始化过程中会通过ServerList从EurekaClient加载负载均衡候选的服务列表,并定时更新服务列表,使用ServerListFilter过滤之后,使用IPing检查是否更新服务列表被注解了LoadBalance标签的RestTemplate可以使用LoadBalancerClient作负载均衡,并添加好拦截器LoadBalancerInterceptor当请求发起RestTemplate会把请求交给LoadBalancerInterceptor拦截器,LoadBalancerInterceptor拦截器调用LoadBalancerClient接收到请求使用ILoadBalancer负载均衡器选择服务,底层用到IRule算法选择好服务之后,LoadBalancerClient把请求交给LoadBalancerRequest去执行
  参考文章
  springcloudopenfeign2。2。2源码分析
  springcloudsourcestudy学习github地址
  微服务入门到入土
  SpringCloud之史上最详细Ribbon源码解读
  SpringCloudRibbon源码解析SpringCloudAlibaba源码解析
投诉 评论 转载

视频号抖音点将罗大佑孙燕姿传统广告疲软直播扛起营收重任5月28日,社交圈仍在回味昨晚的两场线上演唱会上映于微信视频号的罗大佑童年演唱会以及抖音上的孙燕姿你好吗线上唱聊会。两场演唱会均开始于晚上八点,截至各自结束的时间21:3……从A到Z,西工大学子的校园故事3、2、1!我们在工大的故事开始了,每一张照片,每一段故事,都是工大人心中最独特的记忆。点点滴滴构成难忘美好的工大生活,让我们随着字母表,重温那些我们铭刻于心的青春故事。……敏宝饮食替代合集如果宝宝出现以上2项或2项以上的表现,并且反复出现,怀疑牛奶蛋白过敏的可能性大。应及时就医,或做过敏原检测,有针对性的回避饮食!本博主针对最常见的过敏原给大家整理了可作为……Ribbon源码2Ribbon工作流程0。环境nacos版本:1。4。1SpringCloud:Hoxton。SR9SpringBoot:2。4。4SpringCloudalibaba:2。2。5。RELEASES……上学苦?还是上班苦?网上看到有人问:是上学苦?还是上班苦?对于这个问题,我想不同的人答案肯定不一样。但就我个人来讲,如果能给一台时光机让我选择,我愿意选择回到学校里,重温那个青葱的岁月,即便……华为公布超导量子芯片专利专利摘要显示,华为技术有限公司公开了一种超导量子芯片,其中涉及一种超导量子芯片,该超导量子芯片包括至少一个量子处理器,采用集成的电路来进行量子计算,超导量子芯片包括存储单元和量……成都世乒赛淘汰赛开始,男队签位不乐观,这几个精彩看点不容错过成都世乒赛小组赛已结束,根据规则,每组积分第一和第二直接晋级16强,小组第三中世界排名最高的男两支队伍和女队四支队伍晋级16强。接下来,这16支队伍将进行淘汰赛。淘汰赛的……骨科机器人没有达芬奇,谁将是下一个达芬奇在手术机器人领域,直觉外科是一家绕不开的公司。早在2007年,国内就引进了第一台达芬奇手术机器人。虽然已没有了专利壁垒(2020年后到期),但借助先发优势,多年的技……中国男篮官宣换帅,41岁杜锋因祸得福,重返广东朱芳雨才是大赢结束了世界杯预选赛第五个窗口期的比赛之后,杜锋指导和中国男篮全队正在归途当中,中国篮协这边也正式官宣更换主教练。杜锋指导在率领国家队拿到了世界杯的资格之后,功成身退圆满谢幕,不……戴劳力士的人不一定有实力,但戴大金劳的男人一定有背景保安大叔今天的站姿格外标准,在阳光的映射下发条鱼找到了原因,手上那枚大金劳让人直呼大叔简直壕无人性,当时就想问他是否有闺女待嫁。自从戴上金劳之后腰不疼了、腿也不酸了,吃嘛……正确补充维生素的方法你知道吗?补错后果很严重维生素别瞎补,听我说完再做决定,不管你买的是几块钱的普通维生素,还是上百块的复合维生素,这篇文章然有点长,但一定对你很有帮助。维生素分为两大类,脂溶性维生素和水溶性维生素……最奶爸的新能源MPV,上汽大通MAXUSMIFA5家用刚刚好近期,很多品牌推出了新能源MPV,并且都追求高端上档次的定位。但是,对于一般家庭用户来说,他们并不需要这么高端MPV车型,只要足够的实用,而且性价比高的话,就已经符合他们的需求……
淋漓尽致的人性暴露加强版佩顿!勇士正式亮出新争冠阵容,科尔力保一人进轮换人民日报金句选编(七十六)江西赣州新晋富豪张剑萌,19岁中专毕业自谋生路,如今身价24奥运冠军郭晶晶一改往日低调,和贝嫂合拍写真气场爆棚东湖磨山景区处处红旗飘扬,每天两千多人打卡东湖之眼2022年9月券商十大金股人生的道理性能反超Mate50,12G256G售价3999元,性价比做象棋杀棋练习五步杀432旗舰双芯多方位优化,vivoX80游戏表现值得期待中国女篮十二朵金花个人简介,内蒙古五人山东两人免费资源网站合集(干货)康复费可以进行司法鉴定吗美丽的毛樱桃回味无穷的面香献给还没有定下来的年轻人人有三急是哪三急准确答案当然要不负时光啊秋之韵梵克雅宝单花手链分大小号吗梵克雅宝单花手链有中号吗走出童年作文500字张家界跟团和自由行的优劣势,张家界找导游要注意什么美丽的冬雪

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利