springcloud之FeignClient使用詳解
前言
在微服務(wù)項目中會存在多個微服務(wù)之間互相調(diào)用的情況,如何高效便捷的進行遠程過程調(diào)用便成為新的議論話題。spring-cloud中提供的feign方式可以有效解決該問題。
Feign是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務(wù)時能與調(diào)用本地方法一樣的編碼體驗,開發(fā)者完全感知不到這是遠程方法,更感知不到這是個HTTP請求。
如下testMicroServiceAccess方法便是feignClient調(diào)用,但是外部看起來和普通方法無二。
業(yè)務(wù)場景
假設(shè)同一個注冊中心上有兩個微服務(wù):A和B,為完成某個業(yè)務(wù)功能,B微服務(wù)需要調(diào)用A微服務(wù)中的某個方法邏輯獲取返回結(jié)果,并且二者是不能作為jar互相依賴的,按照傳統(tǒng)方式只能如下處理:
請求——>外部網(wǎng)關(guān)——>應(yīng)用層——>內(nèi)部網(wǎng)關(guān)——>B微服務(wù)——>外部網(wǎng)關(guān)——>應(yīng)用層——>內(nèi)部網(wǎng)關(guān)——>A微服務(wù)——>結(jié)束
即便是拆掉外部網(wǎng)關(guān)和應(yīng)用層,也需要通過內(nèi)部網(wǎng)關(guān)中轉(zhuǎn)才能訪問到A微服務(wù),況且還要考慮超時熔斷、路由負載等問題。
引入feign后簡化流程,并且其結(jié)合ribbon實現(xiàn)路由負載超時熔斷等措施,具體流程如下:
請求——>外部網(wǎng)關(guān)——>應(yīng)用層——>內(nèi)部網(wǎng)關(guān)——>B微服務(wù)——>feignClient——>A微服務(wù)——>結(jié)束
架構(gòu)說明
按照上述業(yè)務(wù)假設(shè)進行架構(gòu)說明:
1、為保持系統(tǒng)良好的可擴展性,降低模塊耦合度,新建A-FeignClient模塊,用于提供feign接口和相關(guān)實體類。后期作為jar文件推送到Maven私服中,供A、B微服務(wù)各自引用。
2、A微服務(wù)中僅需要在啟動類上增加開啟feign的注解,可以考慮增加A-FeignClient依賴,這樣三個模塊使用同一份實體類,保證一致性。
3、B微服務(wù)中增加A-FeignClient模塊的依賴,編寫客戶端調(diào)用代碼。
調(diào)用邏輯
1、A-FeignClient
- a、在A-FeignClient中增加接口,通過spring注解標(biāo)識其提供服務(wù)的真正接口路徑。
- b、@FeignClient注解中name值目標(biāo)微服務(wù)名,contextId用于標(biāo)識FeignClient名。
- c、方法名上的postmapping用于標(biāo)識該方法需要轉(zhuǎn)發(fā)的接口路徑。下圖代碼示例中意思即:調(diào)用該方法后會代理到A微服務(wù)的/demoServer/testMicroServiceAccess接口中。
- d、通過實現(xiàn)該接口的方式新建一個類,可以用于feign調(diào)用失敗后的容錯處理。
package com.demo.DemoFeignClient; /** * 微服務(wù)之間調(diào)用的核心接口 Aikes * 注解@FeignClient中contextID參數(shù)用于標(biāo)識client,防止多個接口共用同一個目標(biāo)FeignClient沖突 */ @FeignClient(name = "A-server" ,contextId = "DemoFeignClient", fallback = DemoFeignClientFallback.class ) public interface DemoFeignClient{ @PostMapping("/demoServer/testMicroServiceAccess") public ApiResponse<String> testMicroServiceAccess(@RequestBody ServerAccessRequest<DemoPo> cServerAccessRequest); } /** * 增加訪問失敗時的處理邏輯 */ @Component class DemoFeignClientFallback implements DemoFeignClient{ @Override public ApiResponse<String> testMicroServiceAccess(ServerAccessRequest<DemoPo> cServerAccessRequest) { ApiResponse<String> tApiResponse = new ApiResponse<>(); tApiResponse.setStatus(ApiResponse.BUSY); return tApiResponse; } }
2、A微服務(wù)
作為服務(wù)提供方,只需要正常編寫業(yè)務(wù)邏輯即可,重點需要考慮請求入?yún)⒌膶嶓w類把控,建議引用A-FeignClient中,保證一致性。
package com.demo.DemoFeignServerController; /** * 服務(wù)提供方 Aikes */ @Controller @RequestMapping("demoServer") @RestController @Slf4j public class DemoFeignServerController { @PostMapping("/testMicroServiceAccess") public ApiResponse<String> testMicroServiceAccess(@RequestBody ServerAccessRequest<DemoPo> cServerAccessRequest) { log.info(cServerAccessRequest.toString()); log.info("This is FeignServerController"); ApiResponse<String> tApiResponse = new ApiResponse<String>(); tApiResponse.setStatus(ApiResponse.SUCCESS); tApiResponse.setStatusText(ApiResponse.SUCCESS_TEXT); tApiResponse.setData(cServerAccessRequest.getData().getDemoName()); return tApiResponse; } }
3、B微服務(wù)
作為服務(wù)消費方,在核心邏輯處理中,通過調(diào)用引入的A-FeignClient模塊的接口,由feign負責(zé)代理轉(zhuǎn)發(fā)到A微服務(wù),實現(xiàn)調(diào)用A微服務(wù)的相關(guān)邏輯。
package com.demo.DemoFeignClientController; /** * 服務(wù)消費方 Aikes */ public class DemoFeignClientController { @Autowired private DemoFeignClient mDemoFeignClient; public void doService() { //TODO 業(yè)務(wù)處理 ApiResponse<String> tApiResponse = this.testFeign();//調(diào)用 A微服務(wù) 處理邏輯 //TODO 處理返回結(jié)果 } public ApiResponse<String> testFeign() { ServerAccessRequest<DemoPo> tServerAccessRequest = new ServerAccessRequest<DemoPo>(); tServerAccessRequest.setBusinessNo("TEST001"); return mDemoFeignClient.testMicroServiceAccess(tServerAccessRequest); } }
小結(jié)
通過feign的方式可以降低服務(wù)間調(diào)用的復(fù)雜度,從而提升系統(tǒng)性能。但同時帶來的問題也需要重點考量:
- 1、服務(wù)間調(diào)用失敗后的事務(wù)一致性處理,需要結(jié)合各自業(yè)務(wù)場景分析。
- 2、錯綜復(fù)雜的服務(wù)間調(diào)用開啟后,相當(dāng)于給系統(tǒng)開了后門,需要考慮增加服務(wù)間調(diào)用日志記錄的功能,推薦使用自定義注解+AOP統(tǒng)一處理。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring之spring-context-indexer依賴詳解
這篇文章主要介紹了Spring之spring-context-indexer依賴詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java編寫程序之輸入一個數(shù)字實現(xiàn)該數(shù)字階乘的計算
這篇文章主要介紹了Java編寫程序之輸入一個數(shù)字實現(xiàn)該數(shù)字階乘的計算,本文通過實例代碼給大家介紹的非常想詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02SpringBoot簡單使用SpringData的jdbc和durid
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著SpringBoot簡單使用SpringData的jdbc和durid,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06使用@Value為靜態(tài)變量導(dǎo)入并使用導(dǎo)入的靜態(tài)變量進行初始化方式
這篇文章主要介紹了使用@Value為靜態(tài)變量導(dǎo)入并使用導(dǎo)入的靜態(tài)變量進行初始化方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Springboot vue導(dǎo)出功能實現(xiàn)代碼
這篇文章主要介紹了Springboot vue導(dǎo)出功能實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04