成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

背景

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

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

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

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

只需要在接口聲明處加上一個 URI 參數即可,這樣就可以在每次調用時傳遞不同的 URI 來實現動態 URL 的目的。

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

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

執行后會拋出負載均衡的異常:

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

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

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

Debug

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

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

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

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

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

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

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

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

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

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

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

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

接著從源碼中進行閱讀,會發現是將 @FeignClient 中的所有數據都寫到一個 Map 里進行使用的。

最終會發現這個 url 被寫入到了 FeignClientFactoryBean 中的 url 成員變量中了。

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

在這里打個斷點會發現:當 url 為空時會返回一個 LoadBalance 的 client,也就是會從注冊中心獲取 url 的客戶端,而 url 有值時則會獲取一個默認的客戶端,這樣就不會走負載均衡了。

所以我們如果想在 OpenFeign 中使用動態 url 時就得讓 @Feign 的 url 有值才行,無論是什么都可以。

Feign 的實現

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

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

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

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

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

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

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

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

到此為止這個問題的背后原理都已經分析完畢了。

總結

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

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

所以我也提了一個 PR 給 OpenFeign,感興趣的朋友也可以查看一下:

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

責任編輯:姜華 來源: 今日頭條
相關推薦

2013-09-09 16:11:10

2021-11-05 07:59:25

HashMapJava知識總結

2021-08-26 11:52:32

FeignWeb服務

2025-01-15 13:30:48

FeignHTTPJava

2022-04-08 08:48:16

線上事故日志訂閱者

2014-07-08 09:27:24

SQLSERVER腳本

2018-12-29 08:15:28

Tomcat應用部署

2021-09-28 12:25:30

數據庫

2023-11-28 14:22:54

Python音頻

2013-03-27 15:23:51

Android開發demo下載學習

2023-06-20 08:25:53

NESTED源碼mybatis

2018-11-16 17:00:05

Python腳本數據分析

2019-08-02 15:39:06

PythonLinuxJSON

2010-03-02 16:33:14

linux數據備份

2019-11-21 10:20:05

SQL錯誤用法數據庫

2024-06-26 10:37:05

2020-11-16 11:24:00

Spring AOP數據庫

2019-08-06 13:37:55

微服務架構數據

2022-04-27 07:21:06

HTTPAPI系統

2011-06-02 10:23:33

程序員
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本成人免费观看 | 久久福利网站 | www.久草.com| 日韩一区二区三区在线观看视频 | 国产免费又色又爽又黄在线观看 | 国产精品一区在线 | 一区日韩 | 国产精品视频网站 | 盗摄精品av一区二区三区 | 日本在线小视频 | 国产精品久久久久久亚洲调教 | 天天澡天天狠天天天做 | 欧美影院| 国产精品国产 | 久久久久久免费精品一区二区三区 | 91在线精品视频 | 国产一区二区三区视频 | 91看片网| 亚洲国产成人精品一区二区 | 日韩一区二区三区视频在线播放 | 国产福利91精品一区二区三区 | 国产精品久久久久久久一区探花 | 超碰在线人人 | 日韩一区二区三区在线看 | 国产高清视频一区二区 | www.伊人.com | 亚洲网站在线观看 | 成人精品鲁一区一区二区 | 日本高清不卡视频 | 色资源在线 | 雨宫琴音一区二区在线 | 国产欧美在线视频 | 伊人99| www.欧美视频 | 亚洲高清成人 | 色婷婷九月 | 看片91| 日韩一区二区三区四区五区 | 欧美一级在线观看 | 久久精品99国产精品 | 日韩精品一区二区三区视频播放 |