5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用 @目錄5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用前言1. OpenFeign 介紹1.1 Feign 和 OpenFeign 區(qū)別2. Op
@[toc]
- 對(duì)應(yīng)上一篇學(xué)習(xí)內(nèi)容:??? 4. Spring Cloud Ribbon 實(shí)現(xiàn)“負(fù)載均衡”的詳細(xì)配置說明_ribbon升級(jí)到了loadbalancer-CSDN博客
- 對(duì)應(yīng)下一篇學(xué)習(xí)內(nèi)容:???
OpenFeign 是什么 ?
OpenFeign 是個(gè)聲明式
WebService
客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡(jiǎn)單。
它的使用方法是 定義一個(gè)服務(wù)接口,然后在上面添加注解。
OpenFeign 也支持可插拔式的 編碼器 和 解碼器 。
Spring Cloud 對(duì) OpenFeign 進(jìn)行了封裝使其支持了 Spring MVC 標(biāo)注注解 和
HttpMessageConverters
。
OpenFeign 可以與 Eureka 和 Ribbon 組合使用以支持負(fù)載均衡。
OpenFeign 官網(wǎng)地址: https://github.com/spring-cloud/spring-cloud-openfeign
簡(jiǎn)單的說:就是一個(gè) Web Service 客戶端訪問的,轉(zhuǎn)發(fā)的一個(gè)組件,可以實(shí)現(xiàn) Server 集群的通信,簡(jiǎn)化 Web Service 客戶端 。
Feign:
org.springframework.cloud
spring-cloud-starter-openfeign
OpenFeign:
org.springframework.cloud
spring-cloud-starter-openfeign
需求分析&圖解
示意圖:
參考 member-service-consumer-80 創(chuàng)建 member-service-consumer-openfeign-80(具體步 驟參考以前)
pom.xml
文件當(dāng)中,導(dǎo)入相關(guān)的 jar 依賴。特別是這里:我們的主角
openFeign
。
org.springframework.cloud
spring-cloud-starter-openfeign
完整的 pom.xml 文件信息:
http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
e-commerce-center
com.rainbowsea
1.0-SNAPSHOT
4.0.0
member-service-consumer-openfeign-80
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.rainbowsea
e_commerce_center-common-api
${project.version}
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
application.yml
進(jìn)行一些相關(guān)的配置信息, 內(nèi)容如下:
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因?yàn)檫@里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當(dāng)中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊(cè)到 Eureka-Server 當(dāng)中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當(dāng)中
service-url:
# 表示將自己注冊(cè)到那個(gè) eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務(wù)注冊(cè)到多個(gè) eureka - server 當(dāng)中,使用逗號(hào)間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
member-service-consumer-openfeign-80
的主啟動(dòng)類,也就是場(chǎng)景啟動(dòng)器。
在:創(chuàng)建包
com.rainbowsea.springcloud
,創(chuàng)建名為
MemberConsumerOpenfeignApplication80
的主啟動(dòng)類,如下圖所示:
package com.rainbowsea.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient // 表示作為 Eureka Client 角色
@EnableFeignClients // 啟動(dòng) OpenFeignClient
public class MemberConsumerOpenfeignApplication80 {
public static void main(String[] args) {
SpringApplication.run(MemberConsumerOpenfeignApplication80.class, args);
}
}
添加主啟動(dòng)類之后,我們可以測(cè)試一下,是否成功將該模塊
member-service-consumer-openfeign-80
注冊(cè)到了 Eureka Server 當(dāng)中去了。
注意:下面的操作就是:是 OpenFeign 的核心內(nèi)容了。
member-service-consumer-openfeign-80
模塊當(dāng)中創(chuàng)建一個(gè)
com.rainbowsea.springcloud.service
包,在該包當(dāng)中創(chuàng)建一個(gè)
MemberFeignService
接口,注意注意是接口
interface
不是類。如下圖所示:
package com.rainbowsea.springcloud.service;
import com.rainbowsea.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Component
public interface MemberFeignService {
}
然后我們需要將其中,我們
member-service-consumer-openfeign-80
模塊是作為 Eureka Client 客戶端存在的,這里使用 OpenFeign 簡(jiǎn)化客戶端,我們還需將 ,我們 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調(diào)用的哪個(gè)
provider service(服務(wù)器/服務(wù)集群)
處理我們的業(yè)務(wù),這里我們是
服務(wù)集群
,這里我們有兩個(gè) privoid service 可以處理我們所需的業(yè)務(wù),如下圖所受:分別為:
member-service-provider-10000,member-service-provider-10002 這兩個(gè)服務(wù)(這兩個(gè)服務(wù),是已經(jīng)相互注冊(cè)好了,配置為了服務(wù)集群了 )
這里我們?cè)?
MemberFeignService
接口類上使用
@FeignClient
注解標(biāo)注,我們這個(gè) OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調(diào)用的哪個(gè)
provider service(服務(wù)器/服務(wù)集群)
處理我們的業(yè)務(wù)。如下圖所示:
package com.rainbowsea.springcloud.service;
import com.rainbowsea.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Component
//這里 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務(wù)提供方注冊(cè)的名稱
@FeignClient(value = "MEMBER-SERVICE-PROVIDER") // 這個(gè) value 值就是,對(duì)應(yīng)我們想要訪問的 provider(提供服務(wù)/服務(wù)集群)的 name 名稱
public interface MemberFeignService {
}
同時(shí)我們還需要在
MemberFeignService
接口當(dāng)中定義一個(gè)方法。
注意這個(gè)方法,必須必須和你 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 想要調(diào)用的哪個(gè)
provider service(服務(wù)器/服務(wù)集群)
中的處理對(duì)應(yīng)業(yè)務(wù)的 哪個(gè)方法 ,保持一致(權(quán)限修飾符一致,**Http請(qǐng)求方式(包括了所對(duì)應(yīng)的請(qǐng)求映射路徑)**一致,參數(shù)類型,參數(shù)個(gè)數(shù)一致,返回值類型也是一致的,方法名可以不一致(但強(qiáng)烈建議也保持一致)),所以強(qiáng)烈建議,直接從對(duì)應(yīng)的 provider service 當(dāng)中復(fù)制過來即可。如下圖:我們使用的是getMemberById
根據(jù) id 查詢的業(yè)務(wù)處理。我們只需將其方法名復(fù)制過來即可。
package com.rainbowsea.springcloud.service; import com.rainbowsea.springcloud.entity.Result; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @Component //這里 MEMBER-SERVICE-PROVIDER 就是 Eureka Server 服務(wù)提供方注冊(cè)的名稱 @FeignClient(value = "MEMBER-SERVICE-PROVIDER") // 這個(gè) value 值就是,對(duì)應(yīng)我們想要訪問的 provider(提供服務(wù)/服務(wù)集群)的 name 名稱 public interface MemberFeignService { // 注意:這里定義方法-就是遠(yuǎn)程調(diào)用的接口,建議復(fù)制過來 /* 1.遠(yuǎn)程調(diào)用的方式是get 2.遠(yuǎn)程調(diào)用的 url http://MEMBER-SERVICE-PROVIDER(注冊(cè)到服務(wù)當(dāng)中的別名)/member/get/{id} 3.MEMBER-SERVICE-PROVIDER 就是服務(wù)提供方法 Eureka Server 注冊(cè)的服務(wù) 4. openfeign 會(huì)根據(jù)負(fù)載均衡決定調(diào)用 10000/10002 -默認(rèn)是輪詢 5.因?yàn)閛penfeign 好處是支持了 spring mvc 注解 + 接口解構(gòu) 6. 想要使用 OPFeign 需要在對(duì)應(yīng)場(chǎng)景啟動(dòng)器的位置配置上: @EnableFeignClients // 啟動(dòng) OpenFeignClient */ @GetMapping("/member/get/{id}") Result getMemberById(@PathVariable("id") Long id); }
最后,我們?cè)诋?dāng)前
member-service-consumer-openfeign-80
模塊也就是我們的 OpenFeigin(也就是客戶端,也就是 Eureka Client ) 編寫控制器,在
com.rainbowsea.springcloud.controller
包下,編寫對(duì)應(yīng)的控制器。如下圖所示:
package com.rainbowsea.springcloud.controller;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberFeignService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class MemberConsumerFeignController {
// 裝配MemberFeignService
@Resource
private MemberFeignService memberFeignService;
@GetMapping("/member/consumer/openfeign/get/{id}")
public Result getMemberById(@PathVariable("id") Long id) {
// 調(diào)用接口中的方法
return memberFeignService.getMemberById(id);
}
}
- 特別說明,因?yàn)槲覀兊?OpenFeign 就是一個(gè)通過
接口+注解的
方式作為Eureka Client 客戶端,調(diào)用其中 Service 服務(wù)器- Openfeign 的使用的特點(diǎn):
微服務(wù)接口+@FeignClient
,使用接口進(jìn)行解耦(簡(jiǎn)單的說:就是使用接口調(diào)用對(duì)應(yīng) provider 提供服務(wù)的集群)
測(cè)試,啟動(dòng)服務(wù)器
瀏覽器輸入 : http://localhost/member/consumer/openfeign/get/1
觀察訪問的 10000/10002 端口的服務(wù)是輪詢的
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")
// 這個(gè) value 值就是,對(duì)應(yīng)我們想要訪問的 provider(提供服務(wù)/服務(wù)集群)的 name 名稱 所以:注意不要將提供注冊(cè)的名稱,寫錯(cuò)了
說明 OpenFeign 提供了日志打印功能,可以通過配置來調(diào)整日志級(jí)別,從面對(duì) OpenFeign 接口的調(diào)用情況進(jìn)行監(jiān)控和輸出。
日志級(jí)別:
- NONE: 默認(rèn)的,不顯示任何日志
- BASIC: 僅記錄請(qǐng)求方式,URL,響應(yīng)狀態(tài)碼及執(zhí)行時(shí)間
- HEADERS:除了 BASIC 中定義的信息之外,還有請(qǐng)求和響應(yīng)的頭信息
- FULL: 除了HEADERS 中定義的信息之外,還有請(qǐng)求和響應(yīng)的正文及元數(shù)據(jù)
常見的日志級(jí)別有 5 種,分別是 error、warn、info、debug、trace
- error:錯(cuò)誤日志,指比較嚴(yán)重的錯(cuò)誤,對(duì)正常業(yè)務(wù)有影響,需要運(yùn)維配置監(jiān)控的;
- warn:警告日志,一般的錯(cuò)誤,對(duì)業(yè)務(wù)影響不大,但是需要開發(fā)關(guān)注;
- info:信息日志,記錄排查問題的關(guān)鍵信息,如調(diào)用時(shí)間、出參入?yún)⒌鹊龋?
- debug:用于開發(fā) DEBUG 的,關(guān)鍵邏輯里面的運(yùn)行時(shí)數(shù)據(jù);
- trace:最詳細(xì)的信息,一般這些信息只記錄到日志文件中。
在member-service-consumer-openfeign-80 創(chuàng)建 com.Rainbowsea.springcloud.config.OpenFeignConfig.java 類
package com.rainbowsea.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenFeignConfig {
@Bean
public Logger.Level loggerLever() {
// /日志級(jí)別指定為 FULL
return Logger.Level.FULL;
}
}
在
member-service-consumer-openfeign-80
模塊當(dāng)中修改
application.yml
進(jìn)行配置我們是對(duì)哪個(gè)類進(jìn)行日志打印信息,以及打印配置的日志信息的
級(jí)別
。
logging:
level:
# 對(duì) MemberFeignService 接口調(diào)用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因?yàn)檫@里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當(dāng)中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊(cè)到 Eureka-Server 當(dāng)中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當(dāng)中
service-url:
# 表示將自己注冊(cè)到那個(gè) eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務(wù)注冊(cè)到多個(gè) eureka - server 當(dāng)中,使用逗號(hào)間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
logging:
level:
# 對(duì) MemberFeignService 接口調(diào)用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
測(cè)試
瀏覽器: http://localhost/member/consumer/openfeign/get/1
IDEA 后端查看打印的顯示的日志信息:
OpenFeign 超時(shí): 我們先來看如下一個(gè)問題:
我們模擬網(wǎng)絡(luò)異常,在
member-service-provider-10000
和
member-service-provider-10002
兩個(gè) service 服務(wù)提供方當(dāng)中的
getMemberById
方法,模擬超時(shí) ,這里暫停 5秒。
// 模擬超時(shí) ,這里暫停 5秒
try {
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
瀏覽器訪問 http://localhost/member/consumer/openfeign/get/1
測(cè)試效果:
瀏覽器顯示: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1
IDEA后端顯示: java.net.SocketTimeoutException: Read timed out
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.RetryableException: Read timed out executing GET http://MEMBER-SERVICE-PROVIDER/member/get/1] with root cause
原因分析: OpenFeign 默認(rèn)超時(shí)時(shí)間 1 秒鐘 ,即等待返回結(jié)果 1 秒 ,超過了 1 秒,則會(huì)報(bào)錯(cuò)。
設(shè)置超時(shí)時(shí)間
說明: 在某些情況下,一個(gè)服務(wù)調(diào)用時(shí)間可能要超過 1 秒,就需要重新設(shè)置超時(shí)時(shí)間。
這里我們?cè)O(shè)置超時(shí)時(shí)間設(shè)置為:
8秒
,而我們模擬的是 5秒,5 秒小于 8 秒,可以還在超時(shí)時(shí)間的范圍內(nèi),可以被訪問。
對(duì)于 OpenFeign 超時(shí)時(shí)間,我們需要在
application.yaml
文件當(dāng)中進(jìn)行配置。
如下圖所示:
# OpenFeign 超時(shí)
ribbon:
# #設(shè)置 feign 客戶端超時(shí)時(shí)間(openFeign 默認(rèn)支持 ribbon) #指的是建立連接后從服務(wù)器讀取到可用資源所用的時(shí)間,
# #時(shí)間單位是毫秒
ReadTimeout: 8000
# #指的是建立連接所用的時(shí)間,適用于網(wǎng)絡(luò)狀況正常的情況下,
# #兩端連接所用的時(shí)間
ConnectTimeout: 8000
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
# 配置 eureka client 注意,因?yàn)檫@里該模塊是作為 client 客戶端的角色的,所有要將自己client的信息發(fā)送給 Server 當(dāng)中去的
eureka:
client:
register-with-eureka: true # 表示將自己注冊(cè)到 Eureka-Server 當(dāng)中
fetch-registry: true # 表示將信息發(fā)送到 Eureka-Server 當(dāng)中
service-url:
# 表示將自己注冊(cè)到那個(gè) eureka-server
# defaultZone: http://localhost:9001/eureka
# 將本微服務(wù)注冊(cè)到多個(gè) eureka - server 當(dāng)中,使用逗號(hào)間隔即可
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
logging:
level:
# 對(duì) MemberFeignService 接口調(diào)用過程打印信息-Debug
com.rainbowsea.springcloud.service.MemberFeignService: debug
# OpenFeign 超時(shí)
ribbon:
# #設(shè)置 feign 客戶端超時(shí)時(shí)間(openFeign 默認(rèn)支持 ribbon) #指的是建立連接后從服務(wù)器讀取到可用資源所用的時(shí)間,
# #時(shí)間單位是毫秒
ReadTimeout: 8000
# #指的是建立連接所用的時(shí)間,適用于網(wǎng)絡(luò)狀況正常的情況下,
# #兩端連接所用的時(shí)間
ConnectTimeout: 8000
瀏覽器輸出: http://localhost/member/consumer/openfeign/get/1, 不會(huì)出現(xiàn)超時(shí),會(huì)輪詢?cè)L問 10000/10002
當(dāng)我們?cè)?
pom.xml
當(dāng)中添加了
spring-boot-starter-actuator
的依賴 jar ,就就可以使用該 監(jiān)控系統(tǒng)了。不需要其他的配置
spring-boot-starter-actuator 是spring boot 程序的監(jiān)控系統(tǒng),可以實(shí)現(xiàn)健康檢查,info 信息等
訪問http://localhost:80/actuator 可以看到相關(guān)鏈接,還可以做相關(guān)配置。
spring-boot-starter-actuator
訪問的語法鏈接:url地址+自身模塊對(duì)應(yīng)的端口號(hào)/actuator
。
WebService
客戶端,使用 OpenFeign 讓編寫 Web Service客戶端更簡(jiǎn)單。
微服務(wù)接口+@FeignClient
,使用接口進(jìn)行解耦(簡(jiǎn)單的說:就是使用接口調(diào)用對(duì)應(yīng) provider 提供服務(wù)的集群)
微服務(wù)接口+@FeignClient
,使用接口進(jìn)行解耦(簡(jiǎn)單的說:就是使用接口調(diào)用對(duì)應(yīng) provider 提供服務(wù)的集群)
spring-boot-starter-actuator
訪問的語法鏈接:
url地址+自身模塊對(duì)應(yīng)的端口號(hào)/actuator
。
“在這個(gè)最后的篇章中,我要表達(dá)我對(duì)每一位讀者的感激之情。你們的關(guān)注和回復(fù)是我創(chuàng)作的動(dòng)力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會(huì)將你們的鼓勵(lì)留在心底,繼續(xù)在其他的領(lǐng)域奮斗。感謝你們,我們總會(huì)在某個(gè)時(shí)刻再次相遇!
機(jī)器學(xué)習(xí):神經(jīng)網(wǎng)絡(luò)構(gòu)建(下)
閱讀華為Mate品牌盛典:HarmonyOS NEXT加持下游戲性能得到充分釋放
閱讀實(shí)現(xiàn)對(duì)象集合與DataTable的相互轉(zhuǎn)換
閱讀鴻蒙NEXT元服務(wù):論如何免費(fèi)快速上架作品
閱讀算法與數(shù)據(jù)結(jié)構(gòu) 1 - 模擬
閱讀5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用
閱讀Java代理模式:靜態(tài)代理和動(dòng)態(tài)代理的對(duì)比分析
閱讀Win11筆記本“自動(dòng)管理應(yīng)用的顏色”顯示規(guī)則
閱讀本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]
湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)