目錄
-
Feign 和OpenFeign
- Feign
- OpenFeign
- openFeign的優(yōu)勢
-
OpenFeign應(yīng)用
- 1. 導(dǎo)入依賴
- 2. 使用
- 3. 日志配置
- 4. 數(shù)據(jù)壓縮
-
OpenFeign高級應(yīng)用
- OpenFeign熔斷降級的兩種方式-降級方法和降級工廠
-
踩坑指南
- 坑一:Http Client
- 坑二:全局超時(shí)時(shí)間
- 坑三:單服務(wù)設(shè)置超時(shí)時(shí)間
-
遇到的問題
- 1. 使用Spring MVC注解,但請求方式不正確
- 2. 使用nacos做注冊中心,F(xiàn)eign調(diào)用時(shí)拉取的服務(wù)列表為空
Feign 和OpenFeign
Feign
Feign是Spring Cloud組件中的一個(gè)輕量級RESTful的HTTP服務(wù)客戶端Feign內(nèi)置了Ribbon,用來做客戶端負(fù)載均衡,去調(diào)用服務(wù)注冊中心的服務(wù)。
Feign的使用方式是:使用Feign的注解定義接口,調(diào)用這個(gè)接口,就可以調(diào)用服務(wù)注冊中心的服務(wù)Feign本身不支持Spring MVC的注解,它有一套自己的注解
OpenFeign
OpenFeign是Spring Cloud 在Feign的基礎(chǔ)上支持了Spring MVC的注解,如@RequesMapping等,是一個(gè)輕量級的Http封裝工具對象,大大簡化了Http請求,使得我們對服務(wù)的調(diào)用轉(zhuǎn)換成了對本地接口方法的調(diào)用。
OpenFeign 的 @FeignClient 可以解析SpringMVC的 @RequestMapping注解下的接口,并通過動(dòng)態(tài)代理的方式產(chǎn)生實(shí)現(xiàn)類,實(shí)現(xiàn)類中做負(fù)載均衡并調(diào)用其他服務(wù)
openFeign的優(yōu)勢
- 集成了Ribbon的負(fù)載均衡功能
- 集成Hystrix的熔斷器功能
- 支持請求壓縮
- 大大簡化了遠(yuǎn)程調(diào)用的代碼,同時(shí)功能還增強(qiáng)啦
- 以更加優(yōu)雅的方式編寫遠(yuǎn)程調(diào)用代碼,并簡化重復(fù)代碼
OpenFeign應(yīng)用
1. 導(dǎo)入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
2. 使用
創(chuàng)建Feign接口
@FeignClient(value = "xx-template-service")//value = "xx-template-service"指定服務(wù)的名字
public interface DriverFeign {
/**
* demo feign 接口
*/
@PutMapping(value = "/driver/status")
Driver status(String id, Integer status);
}
Feign會(huì)通過動(dòng)態(tài)代理,幫我們生成實(shí)現(xiàn)類。
注解@FeignClient聲明Feign的客戶端,注解value指明服務(wù)名稱接口定義的方法,采用SpringMVC的注解。Feign會(huì)根據(jù)注解幫我們生成URL地址
FeignClient 注解參數(shù)
- name/value:指定FeignClient的名稱,如果項(xiàng)目使用了Ribbon,name屬性會(huì)作為微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn)
- contextId:指定beanID
- url: url一般用于調(diào)試,可以手動(dòng)指定@FeignClient調(diào)用的地址
- decode404:當(dāng)發(fā)生http 404錯(cuò)誤時(shí),如果該字段位true,會(huì)調(diào)用decoder進(jìn)行解碼,否則拋出FeignException
- configuration: Feign配置類,可以自定義Feign的Encoder、Decoder、LogLevel、Contract
- fallback: 定義容錯(cuò)的處理類,當(dāng)調(diào)用遠(yuǎn)程接口失敗或超時(shí)時(shí),會(huì)調(diào)用對應(yīng)接口的容錯(cuò)邏輯,fallback指定的類必須實(shí)現(xiàn)@FeignClient標(biāo)記的接口
- fallbackFactory: 工廠類,用于生成fallback類示例,通過這個(gè)屬性我們可以實(shí)現(xiàn)每個(gè)接口通用的容錯(cuò)邏輯,減少重復(fù)的代碼
- path: 定義當(dāng)前FeignClient的統(tǒng)一前綴
注意事項(xiàng)
- 在使用fallback、fallbackFactory屬性時(shí),需要使用@Component注解,保證fallback類被Spring容器掃描到
- 在使用FeignClient時(shí),Spring會(huì)按name創(chuàng)建不同的ApplicationContext,通過不同的Context來隔離FeignClient的配置信息, 在使用配置類時(shí),不能把配置類放到Spring App Component scan的路徑下,否則,配置類會(huì)對所有FeignClient生效.
啟用OpenFeign
我們需要在服務(wù)的啟動(dòng)類上開啟 OpenFeign ,只需要在 **Application 啟動(dòng)類上添加 @EnableFeignClients即可。
3. 日志配置
logging:
level:
xx.template.cloud.web.service.feign.ServiceServiceFeign: debug
通過loggin.level.xx=debug來設(shè)置日志級別。然而這個(gè)對Feign客戶端不會(huì)產(chǎn)生效果。因?yàn)锧FeignClient注解修飾的客戶端在被代理時(shí),都會(huì)創(chuàng)建一個(gè)新的Feign.Logger實(shí)例。我們需要額外指定這個(gè)日志的級別才可以。
/**
* feign 日志級別配置
* @return
*/
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
或者在配置文件中配置
feign:
client:
config:
# 全局配置
default:
loggerLevel: full
Feign支持4種級別:
NONE:不記錄任何日志,默認(rèn)值
BASIC:僅記錄請求的方法,URL以及響應(yīng)狀態(tài)碼和執(zhí)行時(shí)間
HEADERS:在BASIC基礎(chǔ)上,額外記錄了請求和響應(yīng)的頭信息
FULL:記錄所有請求和響應(yīng)的明細(xì),包括頭信息、請求體、元數(shù)據(jù)
4. 數(shù)據(jù)壓縮
用戶在網(wǎng)絡(luò)請求過程中,如果網(wǎng)絡(luò)不佳、傳輸數(shù)據(jù)過大,會(huì)造成體驗(yàn)差的問題,我們需要將傳輸數(shù)據(jù)壓縮提升體驗(yàn)。SpringCloud OpenFeign支持對請求和響應(yīng)進(jìn)行GZIP壓縮,以減少通信過程中的性能損耗。
在客戶端中配置數(shù)據(jù)壓縮
feign:
compression:
request:
enabled: true # 開啟請求壓縮
response:
enabled: true # 開啟響應(yīng)壓縮
也可以對請求的數(shù)據(jù)類型,以及觸發(fā)壓縮的大小下限進(jìn)行設(shè)置
feign:
compression:
request:
enabled: true # 開啟請求壓縮
mime-types: text/html,application/xml,application/json # 設(shè)置壓縮的數(shù)據(jù)類型
min-request-size: 2048 # 設(shè)置觸發(fā)壓縮的大小下限
#以上數(shù)據(jù)類型,壓縮大小下限均為默認(rèn)值
response:
enabled: true # 開啟響應(yīng)壓縮
OpenFeign高級應(yīng)用
OpenFeign熔斷降級的兩種方式-降級方法和降級工廠
首先在配置文件中配置如下,開啟熔斷降級
feign.hystrix.enabled=true
-
Feign 定義降級方法
feign接口定義
/** * FeignClient 注解的 fallback 屬性指定降級類 */ @FeignClient(name = "xx-template-cloud-service", fallback = ServiceServiceFeignFallBack.class) public interface ServiceServiceFeign { @GetMapping("/order/getOrder") Result getOrder(String id); }
feign接口降級方法定義
@Slf4j @Component class ServiceServiceFeignFallBack implements ServiceServiceFeign { @Override public Result getOrder(String id) { log.error("Feign接口熔斷 熔斷方式:ServiceServiceFeignFallBack"); return Result.error("500", "Feign接口熔斷"); } }
-
Feign 定義降級工廠
feign接口定義
/** * FeignClient 注解的 fallback 屬性指定降級類 */ @FeignClient(name = "xx-template-cloud-service", fallback = UserCenterFeignClientFallbackFactory.class) public interface ServiceServiceFeign { @GetMapping("/order/getOrder") Result getOrder(String id); }
feign接口降級工廠定義
@Component @Slf4j class UserCenterFeignClientFallbackFactory implements FallbackFactory<ServiceServiceFeign> { @Override public ServiceServiceFeign create(Throwable cause) { return new ServiceServiceFeign() { @Override public Result getOrder(String id) { log.error("Feign接口熔斷,熔斷方式:UserCenterFeignClientFallbackFactory"); return Result.error("500", "Feign接口熔斷"); } }; } }
踩坑指南
坑一:Http Client
OpenFeign默認(rèn)使用jdk自帶的HttpURLConnection,我們知道HttpURLConnection沒有連接池、性能和效率比較低,如果采用默認(rèn),很可能會(huì)遇到性能問題導(dǎo)致系統(tǒng)故障
-
可以采用Apache HttpClient
注意feign-httpclient的版本,如果和Open Feign 不兼容可能會(huì)報(bào)original request is required異常
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>10.10.1</version> </dependency>
feign.httpclient.enabled=true
-
也可以采用OkHttpClient
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> <version>10.2.0</version> </dependency>
feign.okhttp.enabled=true
ribbon中的Http Client
通過OpenFeign作為注冊中心的客戶端時(shí),默認(rèn)使用Ribbon做負(fù)載均衡,Ribbon默認(rèn)也是用jdk自帶的HttpURLConnection,需要給Ribbon也設(shè)置一個(gè)Http client,比如使用okhttp,在properties文件中增加下面配置
ribbon.okhttp.enabled=true
坑二:全局超時(shí)時(shí)間
OpenFeign可以設(shè)置超時(shí)時(shí)間,簡單粗暴,設(shè)置一個(gè)全局的超時(shí)時(shí)間。如果不配置超時(shí)時(shí)間,默認(rèn)是連接超時(shí)10s,讀超時(shí)60s。
feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=60000
但是如果某個(gè)服務(wù)的并發(fā)量很高,服務(wù)的超時(shí)時(shí)間過長會(huì)導(dǎo)致占用大量連接資源,導(dǎo)致系統(tǒng)崩潰,要防止這樣的故障發(fā)生,最好的做法就是給服務(wù)單獨(dú)設(shè)置超時(shí)時(shí)間。
當(dāng)然,如果開啟熔斷后,不配置hystrix和ribbon的超時(shí)時(shí)間,那么Hystrix與ribbon的默認(rèn)請求超時(shí)時(shí)間都是1秒,建議配置Hystrix的超時(shí)時(shí)間要大于ribbon的超時(shí)時(shí)間,否則會(huì)在接口調(diào)用還未完成的時(shí)候直接進(jìn)入回調(diào)方法。
# 開啟熔斷
feign.hystrix.enabled: true
坑三:單服務(wù)設(shè)置超時(shí)時(shí)間
上文所述,對單個(gè)服務(wù)設(shè)置超時(shí)時(shí)間。
feign.client.config.serviceA.connectTimeout=2000
feign.client.config.serviceA.readTimeout=60000
但是如果serviceA中有多個(gè)接口,其中X接口又調(diào)用serviceB的Feign接口,為了保證X接口請求不被單服務(wù)超時(shí)時(shí)間影響,需要單獨(dú)對X接口設(shè)置超時(shí)時(shí)間。
幾個(gè)組件的關(guān)系
hystrix+ribbon。hystrix在最外層,然后再到Ribbon,最后里面的是http請求。所以說。hystrix的熔斷時(shí)間必須大于ribbon的 ( ConnectTimeout + ReadTimeout )。而如果ribbon開啟了重試機(jī)制,還需要乘以對應(yīng)的重試次數(shù)(注意這里的重試可以是ribbon的重試也可能是feign的重試),保證在Ribbon里的請求還沒結(jié)束時(shí),Hystrix的熔斷時(shí)間不會(huì)超時(shí)。
遇到的問題
1. 使用Spring MVC注解,但請求方式不正確
- 參數(shù)沒有通過注解指定,此時(shí)的參數(shù)會(huì)自動(dòng)封裝到body中,F(xiàn)eign檢測到body里面有請求參數(shù)就會(huì)默認(rèn)使用POST請求。
- Feign默認(rèn)使用的是POST方法,如果想使用GET方法,需要在配置文件中設(shè)置spring.cloud.openfeign.client.config.default.method.name=get。
- 如果使用了Spring Cloud Netflix Feign,那么可能是因?yàn)槟膽?yīng)用程序使用了Spring Cloud Netflix Ribbon來處理HTTP負(fù)載均衡。在這種情況下,您需要確保Ribbon的配置正確,并且不會(huì)影響Feign的GET請求。
2. 使用nacos做注冊中心,F(xiàn)eign調(diào)用時(shí)拉取的服務(wù)列表為空
我用的spring cloud版本是Hoxton.SR8
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
原因是Feign 在spring cloud Hoxton.M2版本之后,不再使用ribbon,所以我們在pom文件中還需要導(dǎo)入loadbalancer依賴,并排除掉nacos的ribbon依賴。文章來源:http://www.zghlxwxcb.cn/news/detail-623635.html
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
并在配置文件中添加文章來源地址http://www.zghlxwxcb.cn/news/detail-623635.html
spring.cloud.loadbalancer.ribbon.enabled: false
到了這里,關(guān)于Spring Cloud OpenFeign 的使用及踩坑指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!