java Spring Cloud企業快速開發架構之Ribbon結合RestTemplate實現負載均衡

畏懼小田發表於2022-01-07

在 Spring Cloud 中使用 Ribbon 會更簡單,因為 Spring Cloud 在 Ribbon 的基礎上進行了一層封裝,將很多配置都整合好了。本節將在 Spring Cloud 專案中使用 Ribbon。

使用 RestTemplate 與整合 Ribbon 
Spring 提供了一種簡單便捷的模板類來進行 API 的呼叫,那就是 RestTemplate。

1.使用 RestTemplate 
在前面介紹 Eureka 時,我們已經使用過 RestTemplate 了,本節會更加詳細地跟大家講解 RestTemplate 的具體使用方法。 
首先我們來看看 GET 請求的使用方式:建立一個新的專案 spring-rest-template,配置好 RestTemplate:

1
2
3
4
5
6
7
[object  Object ]@Configuration
public  class  BeanConfiguration {
     @Bean
     public  RestTemplate getRestTemplate() {
         return  new  RestTemplate();
     }
}


新建一個 HouseController,並增加兩個介面,一個透過 @RequestParam 來傳遞引數,返回一個物件資訊;另一個透過 @PathVariable 來傳遞引數,返回一個字串。請儘量透過兩個介面組裝不同的形式,具體程式碼如下所示。

1
2
3
4
5
6
7
8
@GetMapping( "/house/data" )
public  HouseInfo getData(@RequestParam( "name" String  name) {
     return  new  HouseInfo(1L,  "上海"  "虹口"  "東體小區" );
}
@GetMapping( "/house/data/{name}" )
public  String  getData2(@PathVariable( "name" String  name) {
     return  name;
}


新建一個 HouseClientController 用於測試,使用 RestTemplate 來呼叫我們剛剛定義的兩個介面,程式碼如下所示。

1
2
3
4
5
6
7
8
@GetMapping( "/call/data" )
public  HouseInfo getData(@RequestParam( "name" String  name) {
     return  restTemplate.getForObject( ");
}
@GetMapping( "/call/data/{name}" )
public  String  getData2(@PathVariable( "name" String  name) {
     return  restTemplate.getForObject(  "{name}" String . class , name);
}



獲取資料結果可透過 RestTemplate 的 getForObject 方法(如下程式碼所示)來實現,此方法有三個過載的實現:

url:請求的 API 地址,有兩種方式,其中一種是字串,另一種是 URI 形式。 
responseType:返回值的型別。 
uriVariables:PathVariable 引數,有兩種方式,其中一種是可變引數,另一種是 Map 形式。

1
2
3
public  <T> T getForObject( String  url, Class<T> responseType,  Object ... uriVariables);
public  <T> T getForObject( String  url, Class<T> responseType, Map< String , ?> uriVariables);
public  <T> T getForObject(URI url, Class<T> responseType);


除了 getForObject,我們還可以使用 getForEntity 來獲取資料,程式碼如下所示。

1
2
3
4
5
6
7
8
9
@GetMapping( "/call/dataEntity" )
public  HouseInfo getData(@RequestParam( "name" String  name) {
     ResponseEntity<HouseInfo> responseEntity = restTemplate
             .getForEntity(");
     if  (responseEntity.getStatusCodeValue() ==  200 ) {
         return  responseEntity.getBody();
     }
     return  null ;
}


getForEntity 中可以獲取返回的狀態碼、請求頭等資訊,透過 getBody 獲取響應的內容。其餘的和 getForObject 一樣,也是有 3 個過載的實現。

接下來看看怎麼使用 POST 方式呼叫介面。在 HouseController 中增加一個 save 方法用來接收 HouseInfo 資料,程式碼如下所示。

1
2
3
4
5
@PostMapping( "/house/save" )
public  Long addData(@RequestBody HouseInfo houseInfo) {
     System.out.println(houseInfo.getName());
     return  1001L;
}



接著寫呼叫程式碼,用 postForObject 來呼叫,程式碼如下所示。

1
2
3
4
5
6
7
8
9
@GetMapping( "/call/save" )
public  Long add() {
     HouseInfo houseInfo =  new  HouseInfo();
     houseInfo.setCity( "上海" );
     houseInfo.setRegion( "虹口" );
     houseInfo.setName( "×××" );
     Long id = restTemplate.postForObject(");
     return  id;
}



postForObject 同樣有 3 個過載的實現。除了 postForObject 還可以使用 postForEntity 方法,用法都一樣,程式碼如下所示。

1
2
3
public  <T> T postForObject( String  url,  Object  request, Class<T> responseType,  Object ... uriVariables);
public  <T> T postForObject( String  url,  Object  request, Class<T> responseType, Map< String , ?> uriVariables);
public  <T> T postForObject(URI url,  Object  request, Class<T> responseType);


除了 get 和 post 對應的方法之外,RestTemplate 還提供了 put、delete 等操作方法,還有一個比較實用的就是 exchange 方法。exchange 可以執行 get、post、put、delete 這 4 種請求方式。更多地使用方式大家可以自行學習。

2.整合 Ribbon 
在 Spring Cloud 專案中整合 Ribbon 只需要在 pom.xml 中加入下面的依賴即可,其實也可以不用配置,因為 Eureka 中已經引用了 Ribbon,程式碼如下所示。

1
2
3
4
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>



RestTemplate 負載均衡示例 
前面我們呼叫介面都是透過具體的介面地址來進行呼叫,RestTemplate 可以結合 Eureka 來動態發現服務並進行負載均衡的呼叫。

修改 RestTemplate 的配置,增加能夠讓 RestTemplate 具備負載均衡能力的註解 @LoadBalanced。程式碼如下所示。

1
2
3
4
5
6
7
8
@Configuration
public  class  BeanConfiguration {
     @Bean
     @LoadBalanced
     public  RestTemplate getRestTemplate() {
         return  new  RestTemplate();
     }
}



修改介面呼叫的程式碼,將 IP+PORT 改成服務名稱,也就是註冊到 Eureka 中的名稱,程式碼如下所示。

1
2
3
4
@GetMapping( "/call/data" )
public  HouseInfo getData(@RequestParam( "name" String  name) {
     return  restTemplate.getForObject(");
}



介面呼叫的時候,框架內部會將服務名稱替換成具體的服務 IP 資訊,然後進行呼叫。 推薦分散式架構原始碼

@LoadBalanced 註解原理 
相信大家一定有一個疑問:為什麼在 RestTemplate 上加了一個 @LoadBalanced 之後,RestTemplate 就能夠跟 Eureka 結合了,不但可以使用服務名稱去呼叫介面,還可以負載均衡?

應該歸功於 Spring Cloud 給我們做了大量的底層工作,因為它將這些都封裝好了,我們用起來才會那麼簡單。框架就是為了簡化程式碼,提高效率而產生的。

這裡主要的邏輯就是給 RestTemplate 增加攔截器,在請求之前對請求的地址進行替換,或者根據具體的負載策略選擇服務地址,然後再去呼叫,這就是 @LoadBalanced 的原理。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69994808/viewspace-2851234/,如需轉載,請註明出處,否則將追究法律責任。

相關文章