使用FeignClient設置動態Url
FeignClient設置動態Url
1. 需求描述
一般情況下,微服務內部調用都是通過註冊中心,eureka,zookeeper,nacos等實現動態調用,但是對於一些外部http調用,對於不在同一微服務內,不在同一註冊中心的服務調用,可以考慮SpringCloudOpenFeign,而且可以實現動態URL,通過參數動態控制。
2. 實現方案
服務端正常springboot項目,也不一定是springboot項目,隻要正常提供RESTFul接口就可以,本次測試以springboot為例。主要是客戶端調用。
1.服務端:
/** * (Category)控制層 * * @author makejava * @since 2021-06-03 07:20:41 */ @RestController @RequestMapping("/category") public class CategoryController { /** * 服務對象 */ @Resource private CategoryService categoryService; /** * 測試服務 */ @GetMapping("/test") public Response test() { return Response.createSuccessResponse("查詢成功", "我是測試服務"); } }
2.客戶端:
maven依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
客戶端代碼
/** * 測試 * @author zrj * @since 2021-07-25 */ @Api(value = "微盟鑒權測試") @RestController @RequestMapping("/weimob") public class ActivityController { @Resource private CategoryService categoryService; @GetMapping("/test") @ApiOperation(value = "微盟獲取Code") public Response test() throws URISyntaxException { System.out.println("-----測試-----"); URI uri = new URI("http://localhost:8080/category/test"); Response response = categoryService.test(uri); return Response.createSuccessResponse("查詢成功", response); } }
調用接口
/** * 測試接口Openfeign * @author zrj * @since 2021/7/25 **/ @Service("WeimobAuthorize") @FeignClient(url = "http://localhost:8080/category", name = "CategoryService") public interface CategoryService { @GetMapping Response test(URI uri); }
3. 細節分析
1.接口使用SpringMVC註解
接口方法的定義使用瞭SpringMVC的註解 @GetMapping、@RequestParam,其實SpringMVC的其他註解在此處都是支持的。(有其他文章提到也支持OpenFeign原有的註解@RequestLine、@Param等,但博主實測是不支持的,相關解析類為 feign.Contract,這個存疑)。
2.springcloud openfeign自動構建實現類
在使用方式上,OpenFeign需要手動構建代理對象,Spring Cloud OpenFeign 不同於 OpenFeign, Spring Cloud OpenFeign 幫我們自動生成瞭接口的代理對象(即實現類),並且註冊到Spring中,我們可以很方便的使用 @Autowired 註入代理對象然後使用。
其默認的代理對象是 LoadBalancerFeignClient。還有一個代理對象是 feign.Client.Default。
兩者區別在於:LoadBalancerFeignClient 通過服務名(下文提到)從Eureka查找相關的節點地址url,發起調用。feign.Client.Default 僅是簡單的直接調用。
3.FeignClient屬性name與URL一定要指定
@FeignClient(url = “http://localhost:8080/category”, name = “CategoryService”)
name
屬性,是@FeignClient 註解必要的,不定義時會報錯其默認指代Eureka上的服務名。
url
屬性,一定要指定,這是重點瞭! url屬性指定什麼值其實不重要,因為最終都會被方法的URI參數值替換掉,它在這裡另一個重要的作用,就是將接口的代理對象變成feign.Client.Default(上文提到默認是LoadBalancerFeignClient),這樣就繞過瞭從Eureka取節點地址這一步,畢竟第三方的地址不可能註冊到我們的Eureka上。(相關細節可自行debug FeignClientFactoryBean.getTarget())
FeignClient註解配置url屬性實現指定服務方
某天,跟同學聊天,同學說起之前面試的時候面試官提的一個問題:使用spring cloud,現在某個服務有一個新的接口需要驗證。該接口目前隻上線瞭一臺機器,如何指定調用方隻調用這臺機器。問題大致如此,可能有些出入。總結起來,就是希望能夠指定訪問某臺機器。這樣的情況,在我們平時也可能經常遇到。比如甲乙兩人需要調試新接口,但註冊中心隻有一個。可能上面有丙丁戊己庚辛註冊的服務。如果我們按照默認的輪詢的負載均衡規則去調用,七次調用才能輪到乙的服務,根本沒有辦法調試。所以這時候就需要我們能夠指定調用的服務方。
FeignClient註解通過配置url屬性可以指定調用的服務方。我們按照上面的例子,假設乙的IP為192.168.1.2,在端口8080上啟動的服務,那我們就可以把我們的url配置成http://192.168.1.2:8080。這樣調用的就一直是乙的服務瞭。
那我們配置瞭url和不配置url到底產生瞭哪些不同呢?
feign,或者說open-feign底層是使用,我以為默認是httpclient,但是我debug的結果是HttpURLConnection。知道為什麼的可以留言告訴我。feign會基於配置,生成URI。當我們不配置url的時候,URI是這樣的http://service-name/path。使用FeignClien是LoadBalancerFeignClient,該類在處理該URI的時候會對服務名進行解析,也就是從註冊中心查詢該服務名下已經註冊的服務器信息,包括IP和端口。然後將服務名替換成真實的鏈接。而當我們不配置url的時候,使用的FeignClient是Client的默認實現Default,該類就沒有解析的這一步而是直接通過HttpURLConnection進行請求。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 一篇文章教你如何在SpringCloud項目中使用OpenFeign
- 基於springboot服務間Feign調用超時的解決方案
- Spring Cloud-Feign服務調用的問題及處理方法
- OpenFeign服務接口調用的過程詳解
- 剖析SpringCloud Feign中所隱藏的坑