一、概述
在剛才的案例中,我們啟動了一個 user-service ,然後透過DiscoveryClient來獲取服務例項資訊,然後獲取ip和埠來訪問。
但是實際環境中,往往會開啟很多個 user-service 的叢集。此時獲取的服務列表中就會有多個,到底該訪問哪一個呢?
一般這種情況下就需要編寫負載均衡演算法,在多個例項列表中進行選擇。
不過Eureka中已經整合了負載均衡元件:Ribbon,簡單修改程式碼即可使用。
什麼是Ribbon:
接下來,我們就來使用Ribbon實現負載均衡。
二、啟動兩個服務例項
首先我們配置啟動兩個 user-service 例項,一個9091,一個9092。
Eureka監控皮膚:
二、開啟負載均衡
因為Eureka中已經整合了Ribbon,所以我們無需引入新的依賴。
直接修改 consumer-demo\src\main\java\com\itheima\consumer\ConsumerApplication.java
在RestTemplate的配置方法上新增 @LoadBalanced 註解:
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
修改 consumer-demo\src\main\java\com\itheima\consumer\controller\ConsumerController.java 呼叫方式,不再手動獲取ip和埠,而是直接透過服務名稱呼叫;
@GetMapping("{id}") public User queryById(@PathVariable("id") Long id){ String url = "http://user-service/user/" + id; User user = restTemplate.getForObject(url, User.class); return user; }
訪問頁面,檢視結果;並可以在9091和9092的控制檯檢視執行情況:
瞭解:Ribbon預設的負載均衡策略是輪詢。SpringBoot也幫提供了修改負載均衡規則的配置入口在consumerdemo的配置檔案中新增如下,就變成隨機的了:
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
格式是: {服務名稱}.ribbon.NFLoadBalancerRuleClassName
三、原始碼跟蹤
為什麼只輸入了service名稱就可以訪問了呢?之前還要獲取ip和埠。
顯然是有元件根據service名稱,獲取到了服務例項的ip和埠。因為 consumer-demo 使用的是RestTemplate, spring的負載均衡自動配置類LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig 會自動配置負載均衡攔截器(在spring-cloud-commons-**.jar包中的spring.factories中定義的自動配置類),它就是 LoadBalancerInterceptor ,這個類會在對RestTemplate的請求進行攔截,然後從Eureka根據服務id獲取服務列 表,隨後利用負載均衡演算法得到真實的服務地址資訊,替換服務id。
我們進行原始碼跟蹤:
繼續跟入execute方法:發現獲取了9092埠的服務
再跟下一次,發現獲取的是9091、9092之間切換:
多次訪問 consumer-demo 的請求地址;然後跟進程式碼,發現其果然實現了負載均衡。