Ribbon-负载均衡原理
負載均衡原理
SpringCloud底層其實是利用了一個名為Ribbon的組件,來實現負載均衡功能的。
那么我們發出的請求明明是http://userservice/user/1,怎么變成了http://localhost:8081的呢?
源碼跟蹤
為什么我們只輸入了service名稱就可以訪問了呢?之前還要獲取ip和端口。
顯然有人幫我們根據service名稱,獲取到了服務實例的ip和端口。它就是LoadBalancerInterceptor,這個類會在對RestTemplate的請求進行攔截,然后從Eureka根據服務id獲取服務列表,隨后利用負載均衡算法得到真實的服務地址信息,替換服務id。
我們進行源碼跟蹤:
1)LoadBalancerIntercepor
可以看到這里的intercept方法,攔截了用戶的HttpRequest請求,然后做了幾件事:
-
request.getURI():獲取請求uri,本例中就是 http://user-service/user/8
-
originalUri.getHost():獲取uri路徑的主機名,其實就是服務id,user-service
-
this.loadBalancer.execute():處理服務id,和用戶請求。
這里的this.loadBalancer是LoadBalancerClient類型,我們繼續跟入。
2)LoadBalancerClient
繼續跟入execute方法:
代碼是這樣的:
-
getLoadBalancer(serviceId):根據服務id獲取ILoadBalancer,而ILoadBalancer會拿著服務id去eureka中獲取服務列表并保存起來。
-
getServer(loadBalancer):利用內置的負載均衡算法,從服務列表中選擇一個。本例中,可以看到獲取了8082端口的服務
放行后,再次訪問并跟蹤,發現獲取的是8081:
?
果然實現了負載均衡。
3)負載均衡策略IRule
在剛才的代碼中,可以看到獲取服務使通過一個getServer方法來做負載均衡:
?我們繼續跟入:
?
?繼續跟蹤源碼chooseServer方法,發現這么一段代碼:
我們看看這個rule是誰: ?
?這里的rule默認值是一個RoundRobinRule,看類的介紹:
這不就是輪詢的意思嘛。
到這里,整個負載均衡的流程我們就清楚了。
4)總結
SpringCloudRibbon的底層采用了一個攔截器,攔截了RestTemplate發出的請求,對地址做了修改。用一幅圖來總結一下:
基本流程如下:
-
攔截我們的RestTemplate請求http://userservice/user/1
-
RibbonLoadBalancerClient會從請求url中獲取服務名稱,也就是user-service
-
DynamicServerListLoadBalancer根據user-service到eureka拉取服務列表
-
eureka返回列表,localhost:8081、localhost:8082
-
IRule利用內置負載均衡規則,從列表中選擇一個,例如localhost:8081
-
RibbonLoadBalancerClient修改請求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,發起真實請求
總結
以上是生活随笔為你收集整理的Ribbon-负载均衡原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Docker-容器命令案例1
- 下一篇: 服务拆分-服务远程调用