SpringCloud Feign遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解
先來看我們以前利用RestTemplate發(fā)起遠(yuǎn)程調(diào)用的代碼:
存在下面的問題:
- 代碼可讀性差,編程體驗(yàn)不統(tǒng)一
- 參數(shù)復(fù)雜URL難以維護(hù)
1. Feign遠(yuǎn)程調(diào)用
Feign是一個(gè)聲明式的http客戶端,官方地址:https://github.com/OpenFeign/feign
其作用就是幫助我們優(yōu)雅的實(shí)現(xiàn)http請求的發(fā)送,解決上面提到的問題。
1.1.Feign替代RestTemplate
Fegin的使用步驟如下:
1)引入依賴
我們在order-service服務(wù)的pom文件中引入feign的依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2)添加注解
在order-service的啟動(dòng)類添加注解開啟Feign的功能:
3)編寫Feign的客戶端
在order-service中新建一個(gè)接口,內(nèi)容如下:
import cn.itcast.order.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient("userservice") public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
這個(gè)客戶端主要是基于SpringMVC的注解來聲明遠(yuǎn)程調(diào)用的信息,比如:
- 服務(wù)名稱:userservice
- 請求方式:GET
- 請求路徑:/user/{id}
- 請求參數(shù):Long id
- 返回值類型:User
這樣,F(xiàn)eign就可以幫助我們發(fā)送http請求,無需自己使用RestTemplate來發(fā)送了。
4)測試
修改order-service中的OrderService類中的queryOrderById方法,使用Feign客戶端代替RestTemplate:
5)總結(jié)
使用Feign的步驟:
① 引入依賴
② 添加@EnableFeignClients注解
③ 編寫FeignClient接口
④ 使用FeignClient中定義的方法代替RestTemplate
1.2.自定義配置
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)是沒有,不過會(huì)使用Ribbon的重試 |
一般情況下,默認(rèn)值就能滿足我們使用,如果要自定義時(shí),只需要?jiǎng)?chuàng)建自定義的@Bean覆蓋默認(rèn)Bean即可
下面以日志為例來演示如何自定義配置。
1.2.1.配置文件方式
基于配置文件修改feign的日志級別可以針對單個(gè)服務(wù):
feign:
client:
config:
userservice: # 針對某個(gè)微服務(wù)的配置
loggerLevel: FULL # 日志級別
也可以針對所有服務(wù):
feign:
client:
config:
default: # 這里用default就是全局配置,如果是寫服務(wù)名稱,則是針對某個(gè)微服務(wù)的配置
loggerLevel: FULL # 日志級別
而日志的級別分為四種:
- NONE:不記錄任何日志信息,這是默認(rèn)值。
- BASIC:僅記錄請求的方法,URL以及響應(yīng)狀態(tài)碼和執(zhí)行時(shí)間
- HEADERS:在BASIC的基礎(chǔ)上,額外記錄了請求和響應(yīng)的頭信息
- FULL:記錄所有請求和響應(yīng)的明細(xì),包括頭信息、請求體、元數(shù)據(jù)。
1.2.2.Java代碼方式
也可以基于Java代碼來修改日志級別,先聲明一個(gè)類,然后聲明一個(gè)Logger.Level的對象:
public class DefaultFeignConfiguration { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.BASIC; // 日志級別為BASIC } }
如果要全局生效,將其放到啟動(dòng)類的@EnableFeignClients這個(gè)注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
如果是局部生效,則把它放到對應(yīng)的@FeignClient這個(gè)注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
2.Feign使用優(yōu)化
Feign底層發(fā)起http請求,依賴于其它的框架。其底層客戶端實(shí)現(xiàn)包括:
- URLConnection:默認(rèn)實(shí)現(xiàn),不支持連接池
- Apache HttpClient :支持連接池
- OKHttp:支持連接池
因此提高Feign的性能主要手段就是使用連接池代替默認(rèn)的URLConnection。
這里我們用Apache的HttpClient來演示。
1)引入依賴
在order-service的pom文件中引入Apache的HttpClient依賴:
<!--httpClient的依賴 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
2)配置連接池
在order-service的application.yml中添加配置:
feign:
client:
config:
default: # default全局的配置
loggerLevel: BASIC # 日志級別,BASIC就是基本的請求和響應(yīng)信息
httpclient:
enabled: true # 開啟feign對HttpClient的支持
max-connections: 200 # 最大的連接數(shù)
max-connections-per-route: 50 # 每個(gè)路徑的最大連接數(shù)
接下來,在FeignClientFactoryBean中的loadBalance方法中打斷點(diǎn):
Debug方式啟動(dòng)order-service服務(wù),可以看到這里的client,底層就是Apache HttpClient:
總結(jié),F(xiàn)eign的優(yōu)化:
1.日志級別盡量用basic
2.使用HttpClient或OKHttp代替URLConnection
① 引入feign-httpClient依賴
② 配置文件開啟httpClient功能,設(shè)置連接池參數(shù)
3. 最佳實(shí)踐
所謂最近實(shí)踐,就是使用過程中總結(jié)的經(jīng)驗(yàn),最好的一種使用方式。
自習(xí)觀察可以發(fā)現(xiàn),F(xiàn)eign的客戶端與服務(wù)提供者的controller代碼非常相似:
feign客戶端:
UserController:
有沒有一種辦法簡化這種重復(fù)的代碼編寫呢?
3.1.繼承方式
一樣的代碼可以通過繼承來共享:
1)定義一個(gè)API接口,利用定義方法,并基于SpringMVC注解做聲明。
2)Feign客戶端和Controller都集成改接口
優(yōu)點(diǎn):
- 簡單
- 實(shí)現(xiàn)了代碼共享
缺點(diǎn):
- 服務(wù)提供方、服務(wù)消費(fèi)方緊耦合
- 參數(shù)列表中的注解映射并不會(huì)繼承,因此Controller中必須再次聲明方法、參數(shù)列表、注解
3.2.抽取方式
將Feign的Client抽取為獨(dú)立模塊,并且把接口有關(guān)的POJO、默認(rèn)的Feign配置都放到這個(gè)模塊中,提供給所有消費(fèi)者使用。
例如,將UserClient、User、Feign的默認(rèn)配置都抽取到一個(gè)feign-api包中,所有微服務(wù)引用該依賴包,即可直接使用。
3.3.實(shí)現(xiàn)基于抽取的最佳實(shí)踐
1)抽取
首先創(chuàng)建一個(gè)module,命名為feign-api:
項(xiàng)目結(jié)構(gòu):
在feign-api中然后引入feign的starter依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
然后,order-service中編寫的UserClient、User、DefaultFeignConfiguration都復(fù)制到feign-api項(xiàng)目中
2)在order-service中使用feign-api
首先,刪除order-service中的UserClient、User、DefaultFeignConfiguration等類或接口。
在order-service的pom文件中中引入feign-api的依賴:
<dependency> <groupId>cn.itcast.demo</groupId> <artifactId>feign-api</artifactId> <version>1.0</version> </dependency>
修改order-service中的所有與上述三個(gè)組件有關(guān)的導(dǎo)包部分,改成導(dǎo)入feign-api中的包
3)重啟測試
重啟后,發(fā)現(xiàn)服務(wù)報(bào)錯(cuò)了:
這是因?yàn)閁serClient現(xiàn)在在cn.itcast.feign.clients包下,
而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一個(gè)包,無法掃描到UserClient。
4)解決掃描包問題
方式一:
指定Feign應(yīng)該掃描的包:
@EnableFeignClients(basePackages = "xxx.xxx.xxx.clients")
方式二:
指定需要加載的Client接口:
@EnableFeignClients(clients = {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->UserClient.class})
到此這篇關(guān)于SpringCloud Feign遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解的文章就介紹到這了,更多相關(guān)SpringCloud Feign內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于FeignClient調(diào)用超時(shí)的處理方案
這篇文章主要介紹了基于FeignClient調(diào)用超時(shí)的處理方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07java基礎(chǔ)知識之FileInputStream流的使用
這篇文章主要介紹了java基礎(chǔ)知識之FileInputStream流的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Nacos配合SpringBoot實(shí)現(xiàn)動(dòng)態(tài)線程池的基本步驟
使用Nacos配合Spring Boot實(shí)現(xiàn)動(dòng)態(tài)線程池,可以讓你的應(yīng)用動(dòng)態(tài)地調(diào)整線程池參數(shù)而無需重啟,這對于需要高度可配置且需要適應(yīng)不同負(fù)載情況的應(yīng)用來說非常有用,本文給大家介紹實(shí)現(xiàn)動(dòng)態(tài)線程池的基本步驟,需要的朋友可以參考下2024-02-02