分享一個 SpringCloud Feign 中所埋藏的坑

[圖片上傳失敗...(image-883e28-1653318905408)]

背景

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

但也有特殊的须肆,比如我們這里碰到 ToB 場景,需要對每個商戶自定義的 URL 進行調用桩皿。

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

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

[圖片上傳失敗...(image-fd4006-1653318905409)]

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


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

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

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

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

這個異常也能理解斜做,就是找不到 github 這個服務;找不到也是合理的湾揽,畢竟也不是一個內部注冊的服務瓤逼。

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

Debug

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

https://www.cnblogs.com/syui-terra/p/14386188.html

[圖片上傳失敗...(image-e67db5-1653318905409)]

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

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

所以我準備從源碼中找到答案。

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

[圖片上傳失敗...(image-7c7d5a-1653318905409)]
但我在源碼中查看 url 所使用的地方,并沒有在單測之外找到哪里有所應用辈毯,說明源碼中并沒有直接調用 url() 這個函數(shù)來獲取值坝疼。

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

[圖片上傳失敗...(image-4e7eb1-1653318905409)]
最終在這里查到了使用的痕跡钝凶。

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

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

[圖片上傳失敗...(image-5bee4e-1653318905409)]

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


接著從源碼中進行閱讀掏湾,會發(fā)現(xiàn)是將 @FeignClient 中的所有數(shù)據(jù)都寫到一個 Map 里進行使用的。
[圖片上傳失敗...(image-62c7fa-1653318905409)]
最終會發(fā)現(xiàn)這個 url 被寫入到了 FeignClientFactoryBean 中的 url 成員變量中了肿嘲。

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

[圖片上傳失敗...(image-1b3708-1653318905409)]

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

所以我們如果想在 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 便能知道關鍵源碼也拜。

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


[圖片上傳失敗...(image-8f8bd5-1653318905409)]
所以只需要在這個依賴的地方 cmd+shift+f 全局搜索 java.net.URI 就能查到結果趾痘,果然不多慢哈,只有兩處使用。


[圖片上傳失敗...(image-2a7ee3-1653318905409)]
再結合使用場景猜測大概率是判斷參數(shù)中是否是有 URL.class 這樣的條件永票,或者是 url 對象卵贱;總之我們先用
URL 這樣關鍵字在這兩個文件中搜索一下,記得勾選匹配大小寫侣集;最后會發(fā)現(xiàn)的確是判斷了參數(shù)中是否有 URL 這個類键俱,同時將這個索引位置記錄了下來。

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

[圖片上傳失敗...(image-17ccf-1653318905409)]

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

到此為止這個問題的背后原理都已經(jīng)分析完畢了罚攀。

總結

其實本文重點是分析了一些 debug 和閱讀源碼的一些小技巧党觅,特別是在讀關于 Spring 相關的代碼時一定不能 debug 跟蹤到細節(jié)中,因為調用鏈通常是很長的斋泄,稍不留神就把自己都繞暈了杯瞻,只需要知道核心、關鍵源碼是如何處理的即可炫掐。

最后對于 OpenFeign 處理動態(tài) url 的方案確實也有些疑惑魁莉,是一個典型的約定大于配置的場景,但問題就在于我們并不知道這個約定是 @Feign 的 url 得有值募胃。

所以我也提了一個 PROpenFeign旗唁,感興趣的朋友也可以查看一下:

https://github.com/spring-cloud/spring-cloud-openfeign/pull/713

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市痹束,隨后出現(xiàn)的幾起案子检疫,更是在濱河造成了極大的恐慌,老刑警劉巖祷嘶,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屎媳,死亡現(xiàn)場離奇詭異夺溢,居然都是意外死亡,警方通過查閱死者的電腦和手機烛谊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門风响,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丹禀,你說我怎么就攤上這事状勤。” “怎么了湃崩?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵荧降,是天一觀的道長。 經(jīng)常有香客問我攒读,道長朵诫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任薄扁,我火速辦了婚禮剪返,結果婚禮上,老公的妹妹穿的比我還像新娘邓梅。我一直安慰自己脱盲,他們只是感情好,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布日缨。 她就那樣靜靜地躺著钱反,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匣距。 梳的紋絲不亂的頭發(fā)上面哥,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音毅待,去河邊找鬼尚卫。 笑死,一個胖子當著我的面吹牛尸红,可吹牛的內容都是我干的吱涉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼外里,長吁一口氣:“原來是場噩夢啊……” “哼怎爵!你這毒婦竟也來了?” 一聲冷哼從身側響起盅蝗,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鳖链,失蹤者是張志新(化名)和其女友劉穎癣丧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體追他,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡膀息,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年闭专,在試婚紗的時候發(fā)現(xiàn)自己被綠了洼畅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胖替。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡焊唬,死狀恐怖故痊,靈堂內的尸體忽然破棺而出顶瞳,到底是詐尸還是另有隱情,我是刑警寧澤愕秫,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布慨菱,位于F島的核電站,受9級特大地震影響戴甩,放射性物質發(fā)生泄漏符喝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一甜孤、第九天 我趴在偏房一處隱蔽的房頂上張望协饲。 院中可真熱鬧,春花似錦缴川、人聲如沸茉稠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽而线。三九已至,卻和暖如春恋日,著一層夾襖步出監(jiān)牢的瞬間膀篮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工谚鄙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留各拷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓闷营,卻偏偏與公主長得像烤黍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子傻盟,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容