一、什么是遠(yuǎn)程調(diào)用?
在分布式領(lǐng)域中,一個系統(tǒng)由很多服務(wù)組成,不同的服務(wù)由各自的進(jìn)程單獨(dú)負(fù)責(zé)。因此,遠(yuǎn)程調(diào)用在分布式通信中尤為重要。
遠(yuǎn)程調(diào)用可分如下兩類:
- 本地過程調(diào)用(Local Procedure Call,LPC),是指同一臺機(jī)器上運(yùn)行的不同進(jìn)程之間的互相通信,即在多進(jìn)程操作系統(tǒng)中,運(yùn)行的不同進(jìn)程之間可以通過 LPC 進(jìn)行函數(shù)調(diào)用。
- 遠(yuǎn)程過程調(diào)用(Remote Procedure Call,RPC),是指不同機(jī)器上運(yùn)行的進(jìn)程之間的相互通信,某一機(jī)器上運(yùn)行的進(jìn)程在不知道底層通信細(xì)節(jié)的情況下,就像訪問本地服務(wù)一樣,去調(diào)用遠(yuǎn)程機(jī)器上的服務(wù)。
?遠(yuǎn)程調(diào)用的原理
B/S ( Browser/Server,瀏覽器 / 服務(wù)器) 架構(gòu)。在這種架構(gòu)中,被調(diào)用方(服務(wù)器)有一個開放的接口,然后調(diào)用方(用戶)通過 Browser 使用這個接口,來間接調(diào)用被調(diào)用方相應(yīng)的服務(wù),從而實(shí)現(xiàn)遠(yuǎn)程調(diào)用。
基本上通過RPC來實(shí)現(xiàn)遠(yuǎn)程調(diào)用,我們所熟悉的Dubbo,其核心就是RPC遠(yuǎn)程過程調(diào)用
Netty 的底層 就使用到了 RPC 遠(yuǎn)程過程調(diào)用
關(guān)于 Netty 如何實(shí)現(xiàn)RPC遠(yuǎn)程過程調(diào)用的可看我之前的博文 Netty實(shí)戰(zhàn) – 使用Netty實(shí)現(xiàn)分布式框架Dubbo RPC
分布式系統(tǒng)下,遠(yuǎn)程調(diào)用如此重要!
二、RestTemplate 與 Feign 的區(qū)別
RestTemplate 是什么?
RestTemplate
是執(zhí)行HTTP請求的同步阻塞式的客戶端,它在HTTP客戶端庫(例如JDK HttpURLConnection,Apache HttpComponents,okHttp等)基礎(chǔ)封裝了更加簡單易用的模板方法API。也就是說RestTemplate是一個封裝,底層的實(shí)現(xiàn)還是java應(yīng)用開發(fā)中常用的一些HTTP客戶端。但是相對于直接使用底層的HTTP客戶端庫,它的操作更加方便、快捷,能很大程度上提升我們的開發(fā)效率。
RestTemplate 是 遠(yuǎn)程調(diào)用的工具!
在進(jìn)行遠(yuǎn)程調(diào)用時,使用 RestTemplate 時是這樣的
以上代碼的缺點(diǎn):
- 可讀性差,編程風(fēng)格不統(tǒng)一
- 參數(shù)URL復(fù)雜,后期難于維護(hù)
Feign 是什么?
Feign是一個聲明式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單, 它的**使用方法是定義一個接口,然后在上面添加注解
**,同時也支持JAX-RS標(biāo)準(zhǔn)的注解。Feign也支持可拔插式的編碼器和解碼器。**SpringCloud對Feign進(jìn)行了封裝,使其支持了Spring MVC標(biāo)準(zhǔn)注解和HttpMessageConverters。**Feign可以與Eureka和Ribbon組合使用以支持負(fù)載均衡。
Feign 官網(wǎng)地址
使用Feign 可以幫助我們優(yōu)雅的發(fā)送HTTP請求, 可以解決上述的問題!
三、Feign 遠(yuǎn)程調(diào)用 實(shí)戰(zhàn)開發(fā)
?Feign 替代 RestTemplate 實(shí)現(xiàn)遠(yuǎn)程調(diào)用
該項(xiàng)目基于 【云原生】SpringCloud Alibaba 之 Nacos注冊中心實(shí)戰(zhàn) 編寫,源碼后續(xù)我會上傳。
導(dǎo)入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
編寫FeignClient 客戶端類
@FeignClient("userService")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
FeignClient 類解釋
- 服務(wù)名稱:userService
- 請求方式:Get
- 請求路徑:相對路徑 /user/{id} RESTFULL風(fēng)格
- 請求參數(shù):Long id
- 返回結(jié)果:User對象
啟動類開啟支持遠(yuǎn)程調(diào)用功能
// 開啟遠(yuǎn)程調(diào)用服務(wù)
@EnableFeignClients
@SpringBootApplication
@MapperScan("com.chen.order.mapper")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
測試
將order-service 服務(wù)中的 OrderService 類中的 queryOrderById 方法,替代為 FeignClient 寫法
public Order queryOrderById(Long orderId) {
//1. 查詢訂單
Order order = orderMapper.findById(orderId);
//2. 查詢用戶
User user = userClient.findById(order.getUserId());
order.setUser(user);
return order;
}
啟動自行測試即可。
?自定義 Feign 配置
Feign可以支持很多的自定義配置,如下表所示:
類型 | 作用 | 說明 |
---|---|---|
feign.Logger.Level | 修改日志級別 | 包含四種不同的級別:NONE、BASIC、HEADERS、FULL |
feign.codec.Decoder | 響應(yīng)結(jié)果的解析器 | http遠(yuǎn)程調(diào)用的結(jié)果做解析,例如解析json字符串為java對象 |
feign.codec.Encoder | 請求參數(shù)編碼 | 將請求參數(shù)編碼,便于通過http請求發(fā)送 |
feign. Contract | 支持的注解格式 | 默認(rèn)是SpringMVC的注解 |
feign. Retryer | 失敗重試機(jī)制 | 請求失敗的重試機(jī)制,默認(rèn)是沒有,不過會使用Ribbon的重試 |
一般情況下,默認(rèn)值就能滿足我們使用,如果要自定義時,只需要創(chuàng)建自定義的**@Bean覆蓋默認(rèn)Bean即可。**
配置文件的方式配置
基于配置文件修改feign的日志級別可以針對單個服務(wù):
feign:
client:
config:
userservice: # 針對某個微服務(wù)的配置
loggerLevel: FULL # 日志級別
針對所有服務(wù)
feign:
client:
config:
default: # 這里用default就是全局配置,如果是寫服務(wù)名稱,則是針對某個微服務(wù)的配置
loggerLevel: FULL # 日志級別
日志級別分為四種
- NONE:不記錄任何日志信息,默認(rèn)
- BASIC:僅記錄請求的方法,URL以及響應(yīng)狀態(tài)和執(zhí)行時間
- HEADERS:在BASIC的基礎(chǔ)上,加上請求與響應(yīng)頭信息
- FULL:記錄所有請求和響應(yīng)的明細(xì),包括頭信息、請求體、響應(yīng)信息,元數(shù)據(jù)
通過代碼的方式配置
基于Java代碼來修改日志級別,先聲明一個類,然后聲明一個Logger.Level的對象
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class DefaultFeignConfiguration {
@Bean
public Logger.Level logLevel() {
return Logger.Level.BASIC;
}
}
如果想要 全局生效,將其放入 @EnableFeignClients 注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
局部生效,則放入 FeignClients 注解中,指定服務(wù)對其生效:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
四、Feign 使用 優(yōu)化
Feign底層發(fā)起http請求,依賴于其它的框架。其底層客戶端實(shí)現(xiàn)包括:
- URLConnection:默認(rèn)實(shí)現(xiàn),不支持連接池
- Apache HttpClient :支持連接池
- OKHttp:支持連接池
因此提高Feign的性能主要手段就是使用連接池代替默認(rèn)的URLConnection。
Feign的優(yōu)化 小結(jié)
-
日志級別盡量用basic
-
使用HttpClient或OKHttp代替URLConnection
-
引入feign-httpClient依賴
-
配置文件開啟httpClient功能,設(shè)置連接池參數(shù)
五、Feign 最佳實(shí)踐方式
所謂最近實(shí)踐,就是使用過程中總結(jié)的經(jīng)驗(yàn),最好的一種使用方式。
Feign的客戶端與服務(wù)提供者的controller代碼非常相似:
Feign的客戶端
UserController
可以簡化這樣的重復(fù)代碼嗎,答案肯定可以,下面我們就來看看繼承方式來優(yōu)化代碼!
??繼承方式
一樣的代碼可以通過繼承來共享:
1)定義一個API接口,利用定義方法,并基于SpringMVC注解做聲明。
2)Feign客戶端和Controller都繼承該接口
優(yōu)點(diǎn):
- 簡單,通俗易懂
- 實(shí)現(xiàn)了代碼共享
缺點(diǎn):
- 服務(wù)提供方、服務(wù)消費(fèi)方緊耦合
- 參數(shù)列表中的注解映射并不會繼承,因此controller中必須再次聲明方法、參數(shù)列表、注解
??抽取分離方式
將Feign的Client抽取為獨(dú)立模塊,并且把接口有關(guān)的POJO、默認(rèn)的Feign配置都放到這個模塊中,提供給所有消費(fèi)者使用。
例如,將UserClient、User、Feign的默認(rèn)配置都抽取到一個feign-api包中,所有微服務(wù)引用該依賴包,即可直接使用。
代碼實(shí)現(xiàn)
新建一個Moudle
項(xiàng)目結(jié)構(gòu)
pom引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
其次,將Clients、User、DefaultFeignConfiguration 都復(fù)制進(jìn) feign-api
項(xiàng)目中
項(xiàng)目搭建完成、可使用,引入依賴即可
引入依賴使用 feign-api 項(xiàng)目中的配置
在 order-service
項(xiàng)目中引入 feign-api
項(xiàng)目
<dependency>
<groupId>com.wang.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
修改order-service中的所有與上述三個組件有關(guān)的導(dǎo)包部分,改成導(dǎo)入feign-api中的包
重啟測試
重啟測試后,發(fā)現(xiàn)報錯了:
報錯的具體原因是 無法注入該對象,原因是Spring在掃描注入對象的時候,未掃描到該包下的類,所以顯示注入失敗!
UserClient 在 com.chen.feign.clients
包下,而 order-service 的 @EnableFeignClients在 com.chen.order
下,所以無法掃描
解決問題
方式一
指定 Feign 應(yīng)該掃描的包
@EnableFeignClients(basePackages = "com.chen.feign.clients")
方式二
指定需要加載的Client接口
@EnableFeignClients(clients = {UserClient.class})
再次啟動,即可成功!
?小結(jié)
以上就是【Bug 終結(jié)者】對 【云原生】Spring Cloud Alibaba 之 Feign 遠(yuǎn)程調(diào)用 實(shí)戰(zhàn) 的簡單介紹,Spring Cloud Alibaba 是目前比較火的微服務(wù)中間件,很強(qiáng)大,必須吃透!,同時,Feign是目前遠(yuǎn)程調(diào)用最合適的選擇,使用Feign可極大的提高我們的工作效率!文章來源:http://www.zghlxwxcb.cn/news/detail-406334.html
如果這篇【文章】有幫助到你,希望可以給【Bug 終結(jié)者】點(diǎn)個贊??,創(chuàng)作不易,如果有對【后端技術(shù)】、【前端領(lǐng)域】感興趣的小可愛,也歡迎關(guān)注?????? 【Bug 終結(jié)者】??????,我將會給你帶來巨大的【收獲與驚喜】??????!文章來源地址http://www.zghlxwxcb.cn/news/detail-406334.html
到了這里,關(guān)于【云原生】Spring Cloud Alibaba 之 Feign 遠(yuǎn)程調(diào)用 實(shí)戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!