在springcloud中,引入Ribbon來(lái)作為客戶(hù)端時(shí)蚊丐,負(fù)載均衡使用的是被@LoadBalanced
修飾的RestTemplate
對(duì)象诈泼。
RestTemplate詳細(xì)的用法
- GET請(qǐng)求
第一種方式
返回ResponseEntity膝迎,該對(duì)象是Spring對(duì)HTTP請(qǐng)求響應(yīng)的封裝攘须,其中主要存儲(chǔ)了HTTP的幾個(gè)重要元素,HttpStatus代表了錯(cuò)誤碼如404,500等圣贸。以及HttpHeaders代表了請(qǐng)求頭挚歧,body代表了接收到的對(duì)象,其類(lèi)型是根據(jù)第二個(gè)參數(shù)決定的吁峻。第一個(gè)url為請(qǐng)求地址昼激,可以使用{1}占位符庇绽,而參數(shù)的值在該方法的最后的可變參數(shù)。
ResponseEntity<String> forEntity = restTemplate.getForEntity("http://eureka-client/hello",String.class);
String body = forEntity.getBody();
HttpHeaders headers = forEntity.getHeaders();
HttpStatus statusCode = forEntity.getStatusCode();
三個(gè)重載方法:
getForEntity(String url,Class responseType,Object... urlVariables);
getForEntity(String url,Class responseType,Map urlVariables);
getForEntity(URI url,Class responseType);
第二種方式
String forObject = restTemplate.getForObject("http://eureka-client/hello", String.class);
第二種方式與第一種方式唯一的不同就是getForObject的返回值類(lèi)型直接就是參數(shù)列表的第二個(gè)參數(shù)指定的類(lèi)型橙困,所以這種方式?jīng)]法獲取錯(cuò)誤碼和請(qǐng)求頭等信息瞧掺。
RestTemplate本來(lái)是Spring提供的發(fā)送REST請(qǐng)求的工具類(lèi),但是當(dāng)其被@LoadBalanced注解修飾后凡傅,通過(guò)其發(fā)送REST請(qǐng)求辟狈,會(huì)被LoadBalanceInterceptor類(lèi)的inteceptor攔截,然后進(jìn)行一些負(fù)載均衡和請(qǐng)求地址的轉(zhuǎn)換夏跷。
負(fù)載均衡策略
通過(guò)繼承AbstractLoadBalancerRule抽象類(lèi)來(lái)具體實(shí)現(xiàn)負(fù)載均衡策略哼转。
RandomRule
通過(guò)隨機(jī)服務(wù)實(shí)例的數(shù)量來(lái)產(chǎn)生一個(gè)隨機(jī)數(shù),通過(guò)索引獲取該服務(wù)實(shí)例
RoundRobinRule
按照線(xiàn)性輪詢(xún)的方式依次選擇每個(gè)服務(wù)實(shí)例的功能
RetryRule
該策略實(shí)現(xiàn)了一個(gè)具備重試機(jī)制的實(shí)例選擇功能槽华。其內(nèi)部還定義了一個(gè)IRule對(duì)象壹蔓,默認(rèn)使用RoundRobinRule實(shí)例。在choose方法中則實(shí)現(xiàn)了對(duì)內(nèi)部定義的策略進(jìn)行反復(fù)嘗試的策略猫态,若期間能夠選擇到具體的服務(wù)實(shí)例就返回佣蓉,若選擇不到就根據(jù)設(shè)置的嘗試結(jié)束時(shí)間為閥值(maxRetryMillis參數(shù)定義的值+choose方法開(kāi)始執(zhí)行是的時(shí)間戳),當(dāng)超過(guò)該值后就返回null
WeightedResponseTimeRule
該策略是對(duì)RoundRobinRule的擴(kuò)展亲雪,增加了根據(jù)實(shí)例的運(yùn)行情況來(lái)計(jì)數(shù)權(quán)重勇凭,并根據(jù)權(quán)重來(lái)挑選實(shí)例。該策略實(shí)例化的時(shí)候在內(nèi)部創(chuàng)建了一個(gè)定時(shí)任務(wù)义辕,每過(guò)30s便去統(tǒng)計(jì)一下各個(gè)實(shí)例的權(quán)重虾标。
ClientConfigEnableRoundRobinRule
該策略較為特殊,一般不直接使用它灌砖。該策略?xún)?nèi)部定義了一個(gè)RoundRobinRule策略璧函,choose函數(shù)的實(shí)現(xiàn)也是使用了RoundRobinRule的線(xiàn)下輪詢(xún)機(jī)制。一般使用方法:繼承該策略基显,默認(rèn)的choose方法實(shí)現(xiàn)了線(xiàn)性輪詢(xún)機(jī)制柳譬,在子類(lèi)中做一些高級(jí)策略時(shí)通常可能會(huì)存在一些無(wú)法實(shí)施的情況续镇,那么就可以用父類(lèi)的實(shí)現(xiàn)作為備選。
BestAvailableRule
該策略繼承ClientConfigEnableRoundRobinRule销部,在實(shí)現(xiàn)中它注入了負(fù)載均衡器的統(tǒng)計(jì)對(duì)象LoadBalancerStats摸航,同時(shí)在具體的choose算法中利用LoadBalancerStats保存的實(shí)例統(tǒng)計(jì)信息來(lái)滿(mǎn)足要求的實(shí)例。它通過(guò)遍歷負(fù)載均衡器中維護(hù)的所有服務(wù)實(shí)例舅桩,會(huì)過(guò)濾掉故障的實(shí)例酱虎,并找出并發(fā)請(qǐng)求數(shù)最少的一個(gè),所以該策略的特性是可選出最空閑的實(shí)例擂涛。
PredicateBasedRule
抽象策略读串,繼承了ClientConfigEnableRoundRobinRule,基于Predicate實(shí)現(xiàn)的策略,Predicate是Google Guava Collection工具對(duì)集合進(jìn)行過(guò)濾的條件接口恢暖,策略:先過(guò)濾清單排监,在輪詢(xún)選擇
AvailableFilteringRule
繼承自PredicationBasedRule
ZoneAvoidanceRule
繼承自PredicationBasedRule
重試
spring cloud eureka比較注重可用性,所以在極端情況下杰捂,它寧愿接收故障實(shí)例也不會(huì)丟掉“健康”實(shí)例舆床,比如當(dāng)服務(wù)注冊(cè)中心的網(wǎng)絡(luò)發(fā)生故障斷開(kāi)時(shí),由于所有的服務(wù)實(shí)例無(wú)法持續(xù)維持心跳嫁佳,一般的服務(wù)治理會(huì)將所有的服務(wù)實(shí)例剔除挨队,但是eureka則會(huì)因?yàn)槌^(guò)85%的實(shí)例丟失心跳而觸發(fā)保護(hù)機(jī)制,注冊(cè)中心將會(huì)保留此時(shí)的所有節(jié)點(diǎn)蒿往,以實(shí)現(xiàn)服務(wù)間依然可以進(jìn)行互相調(diào)用的場(chǎng)景盛垦,即使其中有部分故障節(jié)點(diǎn),但這樣做可以繼續(xù)保障大多數(shù)的服務(wù)正常消費(fèi)瓤漏。
由于spring cloud eureka咋可用性與一致性上的取舍腾夯,所以我們?cè)趯?shí)現(xiàn)服務(wù)調(diào)用的時(shí)候通常會(huì)加入一些重試機(jī)制。spring cloud 整合了spring retry來(lái)增強(qiáng)RestTemplate的重試能力赌蔑,只需通過(guò)簡(jiǎn)單的配置俯在,原來(lái)那些通過(guò)RestTemplate實(shí)現(xiàn)的服務(wù)訪問(wèn)就會(huì)自動(dòng)根據(jù)配置來(lái)實(shí)現(xiàn)重試策略。
spring.cloud.loadbalancer.retry.enabled=true
#開(kāi)啟重試機(jī)制
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#斷路器的超時(shí)時(shí)間需要大于Ribbon的超時(shí)時(shí)間娃惯,不然不會(huì)觸發(fā)重試
eureka-consumer.ribbon.ConnectTimeout=250
#請(qǐng)求連接的超時(shí)時(shí)間
eureka-consumer.ribbon.ReadTimeout=1000
#請(qǐng)求處理的超時(shí)時(shí)間
eureka-consumer.ribbon.OkToRetryOnAllOperations=true
#對(duì)所有操作請(qǐng)求都進(jìn)行重試
eureka-consumer.ribbon.MaxAutoRetriesNextServer=2
#切換實(shí)例的重試次數(shù)
eureka-consumer.ribbon.MaxAutoRetries=1
#對(duì)當(dāng)前實(shí)例的重試次數(shù)
當(dāng)訪問(wèn)到故障請(qǐng)求的時(shí)候跷乐,它會(huì)在嘗試訪問(wèn)一次當(dāng)前實(shí)例(次數(shù)由MaxAutoRetries配置),如果不行趾浅,就換一個(gè)實(shí)例進(jìn)行訪問(wèn)愕提,如果還是不行,在換一次實(shí)例訪問(wèn)(更換次數(shù)由MaxAutoRetriesNextServer配置)皿哨,如果依然不行浅侨,在返回失敗信息。