摘要:的類圖如下主要根據(jù)創(chuàng)建擴(kuò)展了,創(chuàng)建攔截的,這里會設(shè)置攔截器,這是集成的核心,當(dāng)發(fā)起請求調(diào)用的時候,會先經(jīng)過攔截器,然后才真正發(fā)起請求。和是配合使用的,最大重試次數(shù)是針對每一個的,如果設(shè)置,這樣觸發(fā)最大重試次數(shù)就是次。
上一篇文章我們分析了ribbon的核心原理,接下來我們來看看springcloud是如何集成ribbon的,不同的springcloud的組件(feign,zuul,RestTemplate)集成ribbon有所不同,這篇文章先來看看RestTemplate。
RestTemplate的類圖如下
HttpAccessor主要根據(jù)ClientHttpRequestFactory創(chuàng)建ClientHttpRequest
InterceptingHttpAccessor擴(kuò)展了HttpAccessor,創(chuàng)建攔截的InterceptingClientHttpRequest,這里會設(shè)置攔截器ClientHttpRequestInterceptor,這是集成ribbon的核心,當(dāng)RestTemplate發(fā)起http請求調(diào)用的時候,會先經(jīng)過攔截器,然后才真正發(fā)起http請求。
攔截器ClientHttpRequestInterceptor是如何被設(shè)置的呢?在LoadBalancerAutoConfiguration類中,有如下代碼:
@LoadBalanced @Autowired(required = false) private ListrestTemplates = Collections.emptyList();
只要加入注解@LoadBalanced的RestTemplate會被注入,在沒有引入spring retry組件的時候,加載如下配置:
@Configuration @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") static class LoadBalancerInterceptorConfig { @Bean public LoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); } @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer( final LoadBalancerInterceptor loadBalancerInterceptor) { return new RestTemplateCustomizer() { @Override public void customize(RestTemplate restTemplate) { Listlist = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); } }; } }
這樣RestTemplate就被設(shè)置了LoadBalancerInterceptor,下面來看看整個調(diào)用過程
整個過程有點(diǎn)復(fù)雜,核心就是經(jīng)過攔截器LoadBalancerInterceptor,通過RibbonLoadBalancerClient發(fā)起負(fù)載均衡調(diào)用。RibbonLoadBalancerClientI組合了LoadBalancer,所以具備了負(fù)載均衡的能力,也就是我們在上一篇文章解讀的ribbon原理。
圖中我們沒有畫出真正發(fā)起http請求的過程,其默認(rèn)是由SimpleClientHttpRequestFactory創(chuàng)建,ClientHttpRequestFactory的類圖如下:
從調(diào)用時序圖上我們看到,開始我們調(diào)用的是InterceptingClientHttpRequestFactory來獲取InterceptingClientHttpRequest,它們通過組合的方式集成了ClientHttpRequestFactory和攔截器,InterceptingClientHttpRequest發(fā)起調(diào)用的時候委托了其內(nèi)部類InterceptingRequestExecution去處理,核心邏輯:
@Override public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException { if (this.iterator.hasNext()) { ClientHttpRequestInterceptor nextInterceptor = this.iterator.next(); return nextInterceptor.intercept(request, body, this); }else { ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod()); for (Map.Entry> entry : request.getHeaders().entrySet()) { List values = entry.getValue(); for (String value : values) { delegate.getHeaders().add(entry.getKey(), value); } } if (body.length > 0) { StreamUtils.copy(body, delegate.getBody()); } return delegate.execute(); } }
首先會先取出攔截器集合的第一個執(zhí)行,當(dāng)攔截器執(zhí)行完成后,會回調(diào)回來,執(zhí)行else的代碼,真正發(fā)起http請求,主要有兩種方式實(shí)現(xiàn)ClientHttpRequestFactory接口:
一種是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)創(chuàng)建底層的Http請求連接
一種方式是使用HttpComponentsClientHttpRequestFactory方式,底層使用HttpClient訪問遠(yuǎn)程的Http服務(wù),使用HttpClient可以配置連接池和證書等信息。
?RestTemplate默認(rèn)是使用SimpleClientHttpRequestFactory,內(nèi)部是調(diào)用jdk的HttpConnection,默認(rèn)超時為-1,可以這樣設(shè)置超時時間:
@Bean @LoadBalanced public RestTemplate restTemplate() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(1000 * 2);//連接超時時間 factory.setReadTimeout(1000 * 1);//讀超時時間 return new RestTemplate(factory); }
使用HttpComponentsClientHttpRequestFactory方式可以使用連接池(推薦) ,還可以設(shè)置重試策略(具體沒有研究過)
如果想開啟重試機(jī)制,我們可以引入spring的retry組件
org.springframework.retry spring-retry 版本號
這樣springcloud-ribbon就會加重如下配置:
@Configuration @ConditionalOnClass(RetryTemplate.class) public static class RetryAutoConfiguration { @Bean public RetryTemplate retryTemplate() { RetryTemplate template = new RetryTemplate(); template.setThrowLastExceptionOnExhausted(true); return template; } @Bean @ConditionalOnMissingBean public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() { return new LoadBalancedRetryPolicyFactory.NeverRetryFactory(); } } @Configuration @ConditionalOnClass(RetryTemplate.class) public static class RetryInterceptorAutoConfiguration { @Bean @ConditionalOnMissingBean public RetryLoadBalancerInterceptor ribbonInterceptor( LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties, LoadBalancedRetryPolicyFactory lbRetryPolicyFactory, LoadBalancerRequestFactory requestFactory) { return new RetryLoadBalancerInterceptor(loadBalancerClient, properties, lbRetryPolicyFactory, requestFactory); } @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer( final RetryLoadBalancerInterceptor loadBalancerInterceptor) { return new RestTemplateCustomizer() { @Override public void customize(RestTemplate restTemplate) { Listlist = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); } }; } }
@Bean @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate") @ConditionalOnMissingBean public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory(SpringClientFactory clientFactory) { return new RibbonLoadBalancedRetryPolicyFactory(clientFactory); }
攔截器替換成RetryLoadBalancerInterceptor了,這里集成了retry組件retryTemplate。重試策略由RetryHandler接口來配置,默認(rèn)實(shí)現(xiàn)類DefaultLoadBalancerRetryHandler,如下為默認(rèn)的配置參數(shù)
#最大的重試次數(shù) ribbon.MaxAutoRetries=0 #最大重試server的個數(shù) ribbon.MaxAutoRetriesNextServer=1 #是否開啟任何異常都重試(默認(rèn)在get請求下會重試,其他情況不會重試,除非設(shè)置為true) ribbon.OkToRetryOnAllOperations=false #指定重試的http狀態(tài)碼 ribbon.retryableStatusCodes=500,501
以上是對全局生效,如果加上xxx.ribbon.MaxAutoRetries=1這樣只會對某個ribbon客戶端生效。MaxAutoRetries和MaxAutoRetriesNextServer是配合使用的,最大重試次數(shù)是針對每一個server的,如果設(shè)置MaxAutoRetries=1,MaxAutoRetriesNextServer=1這樣觸發(fā)最大重試次數(shù)就是4次。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76592.html
摘要:當(dāng)服務(wù)宕機(jī)或者不可用時,即請求超時后會調(diào)用此方法。添加電影微服務(wù)啟動類電影微服務(wù)集成斷路器實(shí)現(xiàn)失敗快速響應(yīng),達(dá)到熔斷效果。 SpringCloud(第 014 篇)電影 Ribbon 微服務(wù)集成 Hystrix 斷路器實(shí)現(xiàn)失敗快速響應(yīng),達(dá)到熔斷效果 - 一、大致介紹 1、Hystrix 斷路器的原理很簡單,如同電力過載保護(hù)器。它可以實(shí)現(xiàn)快速失敗,如果它在一段時間內(nèi)偵測到許多類似的錯誤,...
摘要:傳播安全上下文或使用,通過增加的屬性,來增加相關(guān)的配置來達(dá)到執(zhí)行隔離策略,控制線程數(shù)或者控制并發(fā)請求數(shù)來達(dá)到熔斷降級的作用。 SpringCloud(第 015 篇)電影Ribbon微服務(wù)集成Hystrix增加隔離策略控制線程數(shù)或請求數(shù)來達(dá)到熔斷降級的作用 - 一、大致介紹 1、本章節(jié)介紹關(guān)于Hystrix的2種隔離方式(Thread Pool 和 Semaphores); 2、Thr...
摘要:對進(jìn)行了封裝,使其支持標(biāo)準(zhǔn)注解和??梢耘c和組合使用以支持負(fù)載均衡。中使用當(dāng)我們搭建好注冊中心之后,就是需要將自己的服務(wù)注冊到中,然后別的服務(wù)可以直接調(diào)用。 JAVA 項(xiàng)目中接口調(diào)用怎么做 ? Httpclient Okhttp Httpurlconnection RestTemplate 上面是最常見的幾種用法,我們今天要介紹的用法比上面的更簡單,方便,它就是 Feign Feig...
摘要:此為的結(jié)構(gòu)圖上篇已注冊了,的服務(wù),接下來用,實(shí)現(xiàn)負(fù)載均衡和的簡單客戶端,讓消費(fèi)者調(diào)用服務(wù)。是發(fā)布的云中間層服務(wù)開源項(xiàng)目,其主要功能是提供客戶側(cè)軟件負(fù)載均衡算法,將的中間層服務(wù)連接在一起。對選定的負(fù)載均衡策略機(jī)上重試機(jī)制。 ??????????上篇已經(jīng)搭建好基礎(chǔ)demo,接下來繼續(xù)構(gòu)建項(xiàng)目并對spring cloud組件介紹描述。 showImg(https://segmentfault...
閱讀 1902·2021-11-22 15:25
閱讀 1260·2021-11-19 09:40
閱讀 1870·2021-09-27 13:57
閱讀 1002·2021-09-22 15:10
閱讀 980·2021-08-16 11:01
閱讀 2979·2021-07-23 17:51
閱讀 777·2019-08-30 15:55
閱讀 827·2019-08-30 13:58