ribbon 實(shí)現(xiàn)客戶(hù)端的負(fù)載均衡
實(shí)現(xiàn)方式如下所示
只是在RestTemplate方法中加了一個(gè)注解@LoadBalanced
查看注解定義
該注解的作用是mark a RestTemplate bean to be configured to use a LoadBalancerClient
LoadBalanceClient 源碼如下
對(duì)于LoadBalancerClient接口所在包 org.springframework.cloud.client.loadbalancer,
得到如下關(guān)系
LoadBalancerAutoConfiguration為實(shí)現(xiàn)客戶(hù)端負(fù)載均衡的自動(dòng)化配置類(lèi)
在該自動(dòng)化配置類(lèi)中:
① 創(chuàng)建了一個(gè)LoadBalancerInterceptor的Bean狼忱,用于實(shí)現(xiàn)對(duì)客戶(hù)端發(fā)起請(qǐng)求時(shí)進(jìn)行攔截
瑰妄,以實(shí)現(xiàn)客戶(hù)端負(fù)載均衡
② 創(chuàng)建了一個(gè)RestTemplateCustomizer的Bean,用于給RestTemplate增加LoadBalancerInterceptor攔截器
③ 維護(hù)了一個(gè)被@LoadBalanced注解的RestTemplate對(duì)象列表
接下來(lái)阳惹,看一下LoadBalancerInterceptor攔截器
當(dāng)一個(gè)被@LoadBalanced注解的RestTemplate對(duì)象對(duì)外發(fā)起HTTP請(qǐng)求時(shí)象踊,會(huì)被LoadBalancerInterceptor類(lèi)的intercept攔截瑰艘。
LoadBalancerClient下的繼承類(lèi)RibbonLoadBalancerClient础淤,調(diào)用execute方法
execute方法中 getServer獲取具體的服務(wù)實(shí)例
可以看到這里獲取具體服務(wù)實(shí)例的時(shí)候 使用了Netflix Ribbon自身的ILoadBalancer中的chooseServer方法
在ILoadBalancer接口中
對(duì)于該接口的實(shí)現(xiàn),如下
那么在整合Ribbon的時(shí)候Spring Cloud默認(rèn)采用了哪個(gè)具體實(shí)現(xiàn)呢电禀?
在RibbonClientConfiguration配置類(lèi)中,可以看到采用了ZoneAwareLoadBalancer
下面笤休,再回到RibbonLoadBalancerClient的execute方法中尖飞,在通過(guò)ZoneAwareLoadBalancer的
chooseServer方法獲取了負(fù)載均衡分配到的服務(wù)實(shí)例對(duì)象Server之后,將其內(nèi)容包裝成RibbonServer對(duì)象(該對(duì)象除了存儲(chǔ)了服務(wù)實(shí)例的信息之外,還增加了服務(wù)名serviceId政基、是否HTTPS等其它信息)贞铣,然后再回調(diào)LoadBalancerInterceptor請(qǐng)求攔截器中LoadBalancerRequest
的apply(final ServerInstance instance)方法,向一個(gè)實(shí)際的具體服務(wù)實(shí)例發(fā)起請(qǐng)求沮明,
從而實(shí)現(xiàn)一開(kāi)始以服務(wù)名為host的URI請(qǐng)求到host:post形式的實(shí)際訪問(wèn)地址的轉(zhuǎn)換辕坝。
那么apply(final ServiceInstance instance)方法在接收到具體ServiceInstance實(shí)例后,
是如何通過(guò)LoadBalancerClient接口中的reconstructURI()操作來(lái)組成具體請(qǐng)求地址呢荐健?
從apply的實(shí)現(xiàn)中酱畅,可以看到 先生成了ServiceRequestWrapper對(duì)象,該對(duì)象繼承了
HttpRequestWrapper并重寫(xiě)了getURI()方法
在LoadBalancerInterceptor攔截器中摧扇,ClientHttpRequestExecution的實(shí)例具體執(zhí)行
execution.execute(serviceRequest, body)時(shí)圣贸,會(huì)調(diào)用InterceptingClientHttpRequest下
InterceptingRequestExecution中execute方法
可以看到,在創(chuàng)建請(qǐng)求的時(shí)候requestFactory.createRequest(request.getURI(), request.getMethod()); 這里的request.getURI()會(huì)調(diào)用之前的ServiceRequestWrapper.getURI()
就會(huì)使用RibbonLoadBalancerClient.reconstructURI()來(lái)組織具體請(qǐng)求的服務(wù)實(shí)例地址