SpringCloud解析之Ribbon

Ribbon是分佈式微服務架構中負載均衡的一個解決方案,咱們只須要引入ribbon依賴,而後初始化一個RestTemplate對象,在其上添加@LoadBalanced註解,就能夠實現請求的負載均衡,像下面這樣web

image

image

RestTemplate是屬於org.springframework.web.client包下,那麼它是如何經過ribbon實現負載均衡的呢?
SpringBoot在啓動時會加載spring-cloud-commons.jar中的一些自動化配置文件,其中有LoadBalancerAutoConfiguration,看名字你們能夠猜到這個是負載平衡自動配置文件。
首先,它會將全部程序中有@LoadBalanced註解的RestTemplate實例放入一個集合,
image
而後建立一個負載平衡請求工廠LoadBalancerRequestFactory,這裏傳入的loadBalancerClient,實際上是ribbon的RibbonLoadBalancerClient,它實現了
LoadBalancerClient接口
image
接着建立一個負載平衡攔截器LoadBalancerInterceptor,這裏傳入的就是上面的RibbonLoadBalancerClient和LoadBalancerRequestFactory
image

而後,遍歷RestTemplate集合,給每個RestTemplate實例添加上面建立好的LoadBalancerInterceptorspring

image

image

總結起來,LoadBalancerAutoConfiguration就是給全部@LoadBalanced註解的RestTemplate裝上一個負載平衡攔截器LoadBalancerInterceptor。架構

以後,當發起請求執行restTemplate方法時,最後是執行的內部的doExecute方法,它建立的ClientHttpRequest實際上是實現類InterceptingClientHttpRequest,最終調用的是InterceptingClientHttpRequest的內部類InterceptingRequestExecution的execute方法app

image

這裏,從攔截器的迭代器中取出的ClientHttpRequestInterceptor,實際上是它的實現LoadBalancerInterceptor,這就是在LoadBalancerAutoConfiguration中set進去的,而後執行LoadBalancerInterceptor的intercept方法負載均衡

image

在LoadBalancerInterceptor中,最後執行的loadBalancer.execute,是RibbonLoadBalancerClient的方法,別忘了,在LoadBalancerAutoConfiguration中建立的負載平衡攔截器LoadBalancerInterceptor,傳入的初始化參數就是RibbonLoadBalancerClient分佈式

image

RibbonLoadBalancerClient.execute方法中,首先會根據serviceId獲取負載平衡攔截器,而後將其傳入getServer方法中微服務

image

這裏其實仍是調用的攔截器的chooseServer方法,.net

image

最後,調用rule.choose方法,這裏的rule是ribbon的負載平衡規則,ribbon的負載平衡規則有輪詢,隨機,響應時間權重,空閒這麼幾種,默認是輪詢,能夠經過配置指定規則,好比配置成權重MY-PROVIDER.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.WeightedResponseTimeRule3d

(具體每一種規則的邏輯就不在此細說,有興趣的朋友能夠自行查閱)。根據負載平衡規則獲取到具體的Server實例後,將Server包裝成RibbonServer,rest

image

繼續走,

image

終於,最後,執行的是request.apply方法,這裏的request就是LoadBalancerInterceptor.intercept方法中LoadBalancerRequestFactory.createRequest方法建立的request

image

跟着request.apply方法進來,發現將request包裝成了ServiceRequestWrapper,可是這裏並無使用ribbon負載平衡後獲取的服務實例instance,接着走,

image

發現又回到了InterceptingClientHttpRequest的內部類InterceptingRequestExecution的execute方法,

image

這時已經沒有攔截器了,走到else中,要建立一個ClientHttpRequest,createRequest(request.getURI(), request.getMethod())中的request是上面的

ServiceRequestWrapper,咱們看下它的getURI()邏輯

image

image

原來是在這裏,調用了RibbonLoadBalancerClient.reconstructURI方法,在內部經過負載平衡獲取的服務實例組裝成具體的uri,在以後就是常規操做了,拼接請求頭和請求參數,發起請求。

繞了一大圈,作下總結:

添加了@LoadBalanced註解的RestTemplate執行時,會進入LoadBalancerInterceptor的intercept方法,接着會進入ribbon的RibbonLoadBalancerClient類,在該類中經過serviceId獲取負載平衡器,而後經過其內部的負載平衡規則獲取具體的Server實例,最後回到InterceptingClientHttpRequest.execute方法,經過包裝的ServiceRequestWrapper.getURI()方法,調用RibbonLoadBalancerClient.reconstructURI方法拼接具體的請求uri,而後執行http請求。

相關文章
相關標籤/搜索