Analysis of the Springcloud ribbon

Source: Internet
Author: User

The Spring Cloud Ribbon is primarily used for client load balancing. The most basic usage is to use resttemplate for dynamic load balancing. We only need to add the following configuration to complete the client load balancing.

@Configuration  Public class restconfiguration {    @Bean    @LoadBalanced    public  resttemplate Resttemplate () {        returnnew  resttemplate ();    }}
/** Annotation to mark a resttemplate beans to is configured to use a loadbalancerclient @author  */@Target ({elementtype.field, elementtype.parameter, Elementtype.method}) @Retention ( Retentionpolicy.runtime) @Documented @inherited@qualifier public @interface  loadbalanced {}

Here @LoadBalanced使得 RestTemplate can be used LoadBalancerClient, in LoadBalancerClient this way, there is still a LoadBalancerAutoConfiguration configuration class as long as it is used to LoadBalancerClient make configuration. We started with the analysis of the Ribbon as an entry point.

Automated configuration of the LoadBalancer

@Configuration@ConditionalOnClass (resttemplate. class) @ConditionalOnBean (loadbalancerclient. class )@EnableConfigurationProperties (loadbalancerretryproperties.class) Public classloadbalancerautoconfiguration {@LoadBalanced @Autowired (required=false) Private list<resttemplate> resttemplates = collections.emptylist (); @Bean PublicSmartinitializingsingleton Loadbalancedresttemplateinitializer (FinalList<resttemplatecustomizer>customizers) { return NewSmartinitializingsingleton () {@Override Public voidaftersingletonsinstantiated () { for(Resttemplate resttemplate:loadbalancerautoconfiguration. This. Resttemplates) { for(Resttemplatecustomizer customizer:customizers) {customizer.customize (resttemplate); } } } }; } @Autowired (Required=false) PrivateList<loadbalancerrequesttransformer> transformers =collections.emptylist (); @Bean @ConditionalOnMissingBean Publicloadbalancerrequestfactory loadbalancerrequestfactory (loadbalancerclient loadbalancerclient) {return Newloadbalancerrequestfactory (Loadbalancerclient, Transformers); } @Configuration @ConditionalOnMissingClass ("Org.springframework.retry.support.RetryTemplate") Static classLoadbalancerinterceptorconfig {@Bean Public loadbalancerinterceptor ribboninterceptor (loadbalancerclient loadbalancerclient, Loadbalancerrequestfactory requestfactory) {return NewLoadbalancerinterceptor (loadbalancerclient, requestfactory); } @Bean @ConditionalOnMissingBean Public resttemplatecustomizer resttemplatecustomizer (Final loadbalancerinterceptor loadbalancerinterceptor) { return NewResttemplatecustomizer () {@Override Public voidCustomize (Resttemplate resttemplate) {List<ClientHttpRequestInterceptor> list =NewArraylist<>(Resttemplate.getinterceptors ()); List.add (Loadbalancerinterceptor); Resttemplate.setinterceptors (list); } }; } }}

This configuration class mainly does the following several things

1. A bean was created to LoadBalancerInterceptor intercept client-initiated requests in order to achieve client-side load balancing.

2. A bean was created to RestTemplateCustomizer add interceptors to the Resttemplate LoadBalancerInterceptor .

3. Maintain a @LoadBalanced list of annotated RestTemplate objects, and maintain them here, by invoking RestTemplateCustomizer an instance to add interceptors to the required client load Balancer RestTemplate LoadBalancerInterceptor .

Now let's take a look at Loadbalancerinterceptor's intercept, and we'll hit a breakpoint here to see how a resttemplate request was intercepted.

We're org.springframework.http.client.InterceptingClientHttpRequest.InterceptingRequestExecution#execute discovering the following code.

if (this. Iterator.hasnext ()) {                this. Iterator.next ();                 return  This );            }

Here and mybatis more similar, are through the chain of responsibility mode, a layer of interception. In the end it will be loadbalancerinterceptor. Now look at the Intercept method of Loadbalancerinterceptor.

The first two steps are to obtain the request address and servicename, which are provided here for reference.

At first we said,

@LoadBalanced使得RestTemplateYou can use LoadBalancerClient,就是在这里使用LoadBalancerClient的executor方法,做出具体的负载均衡。由于这里的LoadBalancerClient是一个接口,他具体的实现类是 ribbonloadbalancerclient, where we analyze the specific Execute method

 Public<T> T Execute (String serviceId, loadbalancerrequest<t> request)throwsIOException {iloadbalancer loadbalancer=Getloadbalancer (serviceId); Server server = getserver (loadbalancer); if(Server = =NULL) {            Throw NewIllegalStateException ("No instances available for" +serviceId); } ribbonserver ribbonserver=Newribbonserver (serviceId, Server, issecure (server, ServiceId), Serverintrospector (serviceId). GetMetaData        (server)); returnExecute (serviceId, ribbonserver, request); }

The first step to get Loadbalancer,loadbalancer is the interface that defines the operation of the software load balancer, as in the following methods. The default configuration is to use Zoneawareloadbalancer.

 Public InterfaceIloadbalancer {//adding service instances to the list of instances maintained in the load Balancer     Public voidAddservers (list<server>newservers); //pick a specific service instance from the load Balancer     PublicServer chooseserver (Object key); //used to notify and flag that a specific instance of the load balancer has stopped service, or the load balancer will assume that the service instance is normal before the next fetch of the service instance manifest.      Public voidmarkserverdown (server server);//Gets the list of instances of the current normal service     PublicList<server>getreachableservers (); //gets a list of all known service instances, including normal services and stopping service instances.      PublicList<server>getallservers ();}

The second step is to obtain the server according to a certain algorithm, this step is also the core of the whole ribbon, about the specific algorithm logic, we analyze behind

protected Server getserver (iloadbalancer loadbalancer) {        ifnull) {            return  null;        }         return // todo:better handling of key    }

The third step is to pack a ribbonserver after getting to the server

Once a specific server is selected, it can then request that the remaining interceptors will be completed.

 Public<T> T Execute (String serviceId, serviceinstance serviceinstance, loadbalancerrequest<t> request)throwsIOException {Server server=NULL; if(serviceinstanceinstanceofribbonserver) {Server=((ribbonserver) serviceinstance). Getserver (); }        if(Server = =NULL) {            Throw NewIllegalStateException ("No instances available for" +serviceId); } Ribbonloadbalancercontext Context= This. Clientfactory. Getloadbalancercontext (SERVICEID); Ribbonstatsrecorder Statsrecorder=NewRibbonstatsrecorder (context, server); Try{ T returnval = request.apply (serviceinstance);            Statsrecorder.recordstats (ReturnVal); returnReturnVal; }return NULL; }

Finally, a specific request is created and executed.

 PublicClienthttpresponse Execute (HttpRequest request,byte[] body)throwsIOException {if( This. Iterator.hasnext ()) {Clienthttprequestinterceptor Nextinterceptor= This. Iterator.next (); returnNextinterceptor.intercept (Request, Body, This); }            Else{ clienthttprequest delegate = requestfactory.createrequest (Request.geturi (), Request.getmethod ());  for(Map.entry<string, list<string>>entry:request.getHeaders (). EntrySet ()) {List<String> values =Entry.getvalue ();  for(String value:values) {delegate.getheaders (). Add (Entry.getkey (), value); }                }                if(Body.length > 0) {streamutils.copy (body, delegate.getbody ()); }                returnDelegate.execute (); }        }

The above is the analysis of the general process of the Ribbon

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.