Spring Cloud-04使用Ribbon實現客戶端負載均衡
文章目錄
概述
Spring Cloud-03將微服務註冊到Eureka Server上 + 為Eureka Server新增使用者認證中遺留的問題還記得吧 ,對,服務消費者呼叫服務提供者是硬編碼的方式,雖然把地址配置到了application.yml中,但是一旦服務端的地址發生改變,那肯定是要修改配置檔案的。
如何解決呢? Spring Cloud整合了Ribbon.
Ribbon是Nextflix釋出的負載均衡器,為Ribbon配置服務提供者地址後,Ribbon就可以基於某種負載均衡的演算法,自動幫助服務消費者請求。
Ribbon支援輪詢、隨機等負載均衡演算法,當然也支援實現自定義的負載均衡演算法。
在Spring Cloud中,當Ribbon和Eureka配合使用時,Ribbon可自動從Eureka Server獲取服務提供者的地址列表,並基於某種負載均衡演算法,請求其中一個服務提供者例項。
Ribbon演示
服務提供者微服務改造為使用MySql資料庫
當然了,這一步不是必須的。
Step1 修改pom.xml增加mysql的依賴
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Step2: applicaiton.yml中關於資料庫的部分調整為
spring:
datasource:
url: jdbc:mysql://localhost:3306/artisan?useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
新建服務消費者微服務,配置Ribbon
Step1: 為了方便,我們複製下micorservice-consumer-movie,修改為micorservice-consumer-movie-ribbon
Step2: pom.xml引入ribbon依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Step3: 為RestTemplate新增@LoadBalanced註解
只需要為RestTemplate新增@LoadBalanced註解,就可以為RestTemlate整合Ribbon,使其具備負載均衡的能力
Step4: 修改Controller層程式碼,將地址調整為註冊在Eureka上的虛擬主機名
package com.artisan.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.artisan.microservice.model.User;
import lombok.extern.slf4j.Slf4j;
@RestController
@Slf4j
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/movie/{id}")
public User findById(@PathVariable Long id) {
// 呼叫註冊在Eureka上的服務端的地址
return this.restTemplate.getForObject("http://microservice-provider-user/user/" + id, User.class);
}
@GetMapping("/callProvider")
public String callUserInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
// 列印當前選擇的哪個節點
log.info("serviceId: {} , host: {} ,port: {} ,uri: {}" ,serviceInstance.getServiceId() , serviceInstance.getHost(), serviceInstance.getPort(),serviceInstance.getUri());
return serviceInstance.getUri().toString();
}
}
我們把地址修改為了http://microservice-provider-user/user , 其中
microservice-provider-user使用者微服務的虛擬主機名,是註冊在Eureka Server上的名字,也是服務提供者微服務的配置檔案中配置的spring.application.name
當Ribbon和Eureka同時使用時,會自動將虛擬主機名對映為微服務的網路地址。
同時為了更加直觀的獲取當前選擇的使用者微服務節點,我們新增加了個方法callProvider,待會測試就可以看到效果了。
Step5: 驗證Ribbon提供的能力
1.啟動Eureka Server
2.啟動兩個 microservice-provider-user例項 。(在STS中啟動一個後,修改下application.yml的埠,再次run as spring boot app 即可啟動第二個例項,以此類推)
3.啟動microservice-provider-movie-ribbon
4.訪問Eureka Server的頁面,檢視是否註冊成功
登入後,可以看到2個服務提供者,1個服務消費者都成功的註冊到了Eureka Server上。
我們在服務消費者微服務,呼叫的地址為
,對應兩個服務提供者的地址。
同時我們在服務消費者微服務工程中,為RestTemplate標註了@LoadBalanced註解,所以會使用Ribbon的負載均衡演算法來分發到不同的服務提供者地址
多次訪問 http://localhost:7902/movie/1 ,觀察控制檯每個節點的日誌輸出情況。
同時訪問http://localhost:7902/callProvider
注意事項
-
預設情況下,虛擬主機名和服務名稱是一致的,也可以通過eureka.instance.virtual-host-name或者eureka.instance.secure-virtual-host-name指定虛擬主機名
-
不能將restTemplate.getForObject()和loadBalancerClient寫在同一個方法中,兩者會衝突,因為RestTemplate實際上是一個Ribbon客戶端,本身已經包含了choose的行為
-
虛擬主機名不能包含"_"之類的字元,否則Ribbon再呼叫的時候會丟擲異常