通過《Spring Cloud Alibaba基礎教程:使用Nacos實現服務註冊與發現》一文的學習,我們已經學會如何使用Nacos來實現服務的註冊與發現,同時也介紹如何通過LoadBalancerClient介面來獲取某個服務的具體例項,並根據例項資訊來發起服務介面消費請求。但是這樣的做法需要我們手工的去編寫服務選取、連結拼接等繁瑣的工作,對於開發人員來說非常的不友好。所以接下來,我們再來看看除此之外,還支援哪些其他的服務消費方式。
使用RestTemplate
在之前的例子中,已經使用過RestTemplate
來向服務的某個具體例項發起HTTP請求,但是具體的請求路徑是通過拼接完成的,對於開發體驗並不好。但是,實際上,在Spring Cloud中對RestTemplate做了增強,只需要稍加配置,就能簡化之前的呼叫方式。
比如:
@EnableDiscoveryClient
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/test")
public String test() {
String result = restTemplate.getForObject("http://alibaba-nacos-discovery-server/hello?name=didi", String.class);
return "Return : " + result;
}
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
可以看到,在定義RestTemplate的時候,增加了@LoadBalanced
註解,而在真正呼叫服務介面的時候,原來host部分是通過手工拼接ip和埠的,直接採用服務名的時候來寫請求路徑即可。在真正呼叫的時候,Spring Cloud會將請求攔截下來,然後通過負載均衡器選出節點,並替換服務名部分為具體的ip和埠,從而實現基於服務名的負載均衡呼叫。
關於這種方式,可在文末倉庫檢視完整程式碼示例。而對於這種方式的實現原理,可以參考我之前寫的這篇文章的前半部分:Spring Cloud原始碼分析(二)Ribbon
使用WebClient
WebClient是Spring 5中最新引入的,可以將其理解為reactive版的RestTemplate。下面舉個具體的例子,它將實現與上面RestTemplate一樣的請求呼叫:
@EnableDiscoveryClient
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
private WebClient.Builder webClientBuilder;
@GetMapping("/test")
public Mono<String> test() {
Mono<String> result = webClientBuilder.build()
.get()
.uri("http://alibaba-nacos-discovery-server/hello?name=didi")
.retrieve()
.bodyToMono(String.class);
return result;
}
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
可以看到,在定義WebClient.Builder的時候,也增加了@LoadBalanced
註解,其原理與之前的RestTemplate時一樣的。關於WebClient的完整例子也可以通過在文末的倉庫中檢視。
使用Feign
上面介紹的RestTemplate和WebClient都是Spring自己封裝的工具,下面介紹一個Netflix OSS中的成員,通過它可以更方便的定義和使用服務消費客戶端。下面也舉一個具體的例子,其實現內容與上面兩種方式結果一致:
第一步:在pom.xml
中增加openfeign的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
第二步:定義Feign客戶端和使用Feign客戶端:
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
Client client;
@GetMapping("/test")
public String test() {
String result = client.hello("didi");
return "Return : " + result;
}
}
@FeignClient("alibaba-nacos-discovery-server")
interface Client {
@GetMapping("/hello")
String hello(@RequestParam(name = "name") String name);
}
}
這裡主要先通過@EnableFeignClients
註解開啟掃描Spring Cloud Feign客戶端的功能;然後又建立一個Feign的客戶端介面定義。使用@FeignClient
註解來指定這個介面所要呼叫的服務名稱,介面中定義的各個函式使用Spring MVC的註解就可以來繫結服務提供方的REST介面,比如下面就是繫結alibaba-nacos-discovery-server
服務的/hello
介面的例子。最後,在Controller中,注入了Client介面的實現,並呼叫hello方法來觸發對服務提供方的呼叫。關於使用Feign的完整例子也可以通過在文末的倉庫中檢視。
深入思考
如果之前已經用過Spring Cloud的讀者,肯定會這樣的感受:不論我用的是RestTempalte
也好、還是用的WebClient
也好,還是用的Feign
也好,似乎跟我用不用Nacos沒啥關係?我們在之前介紹Eureka和Consul的時候,也都是用同樣的方法來實現服務呼叫的,不是嗎?
確實是這樣,對於Spring Cloud老手來說,就算我們更換了Nacos作為新的服務註冊中心,其實對於我們應用層面的程式碼是沒有影響的。那麼為什麼Spring Cloud可以帶給我們這樣的完美編碼體驗呢?實際上,這完全歸功於Spring Cloud Common的封裝,由於在服務註冊與發現、客戶端負載均衡等方面都做了很好的抽象,而上層應用方面依賴的都是這些抽象介面,而非針對某個具體中介軟體的實現。所以,在Spring Cloud中,我們可以很方便的去切換服務治理方面的中介軟體。
程式碼示例
本文示例讀者可以通過檢視下面倉庫:
- Github:https://github.com/dyc87112/SpringCloud-Learning/
- Gitee:https://gitee.com/didispace/SpringCloud-Learning/
其中,本文的幾種示例可檢視下面的幾個專案:
alibaba-nacos-discovery-server
:服務提供者,必須啟動alibaba-nacos-discovery-client-resttemplate
:使用RestTemplate消費alibaba-nacos-discovery-client-webclient
:使用WebClient消費alibaba-nacos-discovery-client-feign
:使用Feign消費
如果您對這些感興趣,歡迎star、follow、收藏、轉發給予支援!