溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringCloud?Feign中所隱藏的坑實例分析

發(fā)布時間:2022-08-09 09:47:46 來源:億速云 閱讀:127 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“SpringCloud Feign中所隱藏的坑實例分析”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“SpringCloud Feign中所隱藏的坑實例分析”文章能幫助大家解決問題。

背景

前段時間同事碰到一個問題,需要在 SpringCloud 的 Feign 調(diào)用中使用自定義的 URL;通常情況下是沒有這個需求的;畢竟都用了 SpringCloud 的了,那服務(wù)之間的調(diào)用都是走注冊中心的,不會需要自定義 URL 的情況。

但也有特殊的,比如我們這里碰到 ToB 場景,需要對每個商戶自定義的 URL 進(jìn)行調(diào)用。

雖說也可以使用原生的 Feign 甚至是自定義一個 OKHTTP Client 實現(xiàn),但這些方案都得換一種寫法;

打算利用現(xiàn)有的 SpringCloud OpenFeign 來實現(xiàn),畢竟原生的 Feign 其實是支持該功能的,而 SpringCloud OpenFeign 也只是在這基礎(chǔ)上封裝了一層。

SpringCloud?Feign中所隱藏的坑實例分析

只需要在接口聲明處加上一個 URI 參數(shù)即可,這樣就可以在每次調(diào)用時傳遞不同的 URI 來實現(xiàn)動態(tài) URL 的目的。

想法很簡單,但實踐起來卻不是那么回事了。 偽代碼如下:

	@FeignClient(name = "dynamic")
	interface DynamicClient {
		@GetMapping("/")
		String get(URI uri);
	}
	dynamicClient.get(URI.create("https://github.com"));	

執(zhí)行后會拋出負(fù)載均衡的異常:

java.lang.RuntimeException: com.netflix.client.ClientException:
Load balancer does not have available server for client: github.com

這個異常也能理解,就是找不到 github 這個服務(wù);找不到也是合理的,畢竟也不是一個內(nèi)部注冊的服務(wù)。

但按照 Feign 的官方介紹,只要接口中聲明了 URI 這個參數(shù)就能自定義,同時我自己也用原生的 Feign 測試過確實沒什么問題。

Debug

那問題只能出在 SpringCloud OpenFeign 的封裝上了;經(jīng)過同事的搜索在網(wǎng)上找到一篇博客解決了這個問題。

SpringCloud?Feign中所隱藏的坑實例分析

按照文中的說法,確實只需要加上 URL 參數(shù)同時有值就可以了,但原因不明。

本著打破砂鍋問到底的精神,我個人也想知道 OpenFeign 是如何處理的,只要 url 有值就可以,這完全是個黑盒,而且在官方的注釋中并沒有對這種情況有特殊說明。

所以我準(zhǔn)備從源碼中找到答案。

既然是 url 有值就能正常運行,那一定是在運行過程中獲取了這個值;

SpringCloud?Feign中所隱藏的坑實例分析

但我在源碼中查看 url 所使用的地方,并沒有在單測之外找到哪里有所應(yīng)用,說明源碼中并沒有直接調(diào)用 url() 這個函數(shù)來獲取值。

org.springframework.cloud.openfeign.FeignClient 這個注解總會使用吧,于是我又查詢這個注解的使用情況。

SpringCloud?Feign中所隱藏的坑實例分析

最終在這里查到了使用的痕跡。

這里查閱源碼時也有一些小技巧,比如如果我們直接查詢時,IDEA 默認(rèn)的查詢范圍是整個項目和所有依賴庫,會有許多干擾信息。

比如我這里就需要只看項目源碼,單測這些都不用看;所以在查詢的時候可以過濾一下,這樣干擾信息就會少很多。

SpringCloud?Feign中所隱藏的坑實例分析

左邊的工具欄還有許多過濾條件,大家可以自行研究一下。

接著從源碼中進(jìn)行閱讀,會發(fā)現(xiàn)是將 @FeignClient 中的所有數(shù)據(jù)都寫到一個 Map 里進(jìn)行使用的。

SpringCloud?Feign中所隱藏的坑實例分析

最終會發(fā)現(xiàn)這個 url 被寫入到了 FeignClientFactoryBean 中的 url 成員變量中了。

查看哪里在使用這個 url 就知道背后的原理了。

SpringCloud?Feign中所隱藏的坑實例分析

在這里打個斷點會發(fā)現(xiàn):當(dāng) url 為空時會返回一個 LoadBalanceclient,也就是會從注冊中心獲取 url 的客戶端,而 url 有值時則會獲取一個默認(rèn)的客戶端,這樣就不會走負(fù)載均衡了。

所以我們?nèi)绻朐?OpenFeign 中使用動態(tài) url 時就得讓 @Feign 的 url 有值才行,無論是什么都可以。

Feign 的實現(xiàn)

既然已經(jīng)看到這一步了,我也比較好奇 Feign 是如何做到只要有 URI 參數(shù)就使用指定的 URL 呢?

這里也分享一個讀源碼的小技巧,如果我們跟著程序執(zhí)行的思路去一步步 debug 的話會非常消耗時間,畢竟這類成熟庫的代碼量也不小。

這里我們從官方文檔中可以得知只要在接口參數(shù)中使用了 java.net.URI 便會走自定義的 url,所以我們反過來只要在源碼中找到哪里在使用 java.net.URI 便能知道關(guān)鍵源碼。

畢竟使用 java.net.URI 的場景也不會太多。

SpringCloud?Feign中所隱藏的坑實例分析

所以只需要在這個依賴的地方 cmd+shift+f 全局搜索 java.net.URI 就能查到結(jié)果,果然不多,只有兩處使用。

SpringCloud?Feign中所隱藏的坑實例分析

再結(jié)合使用場景猜測大概率是判斷參數(shù)中是否是有 URL.class 這樣的條件,或者是 url 對象;總之我們先用 URL 這樣關(guān)鍵字在這兩個文件中搜索一下,記得勾選匹配大小寫;最后會發(fā)現(xiàn)的確是判斷了參數(shù)中是否有 URL 這個類,同時將這個索引位置記錄了下來。

想必后續(xù)會通過這個索引位置讀取最終的 url 信息。

SpringCloud?Feign中所隱藏的坑實例分析

最終通過這個索引的使用地方查詢到了核心源碼,如果有值時就取這個 URI 中所指定的地址作為 target。

關(guān)于“SpringCloud Feign中所隱藏的坑實例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI