欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

剖析SpringCloud Feign中所隱藏的坑

 更新時(shí)間:2022年08月08日 16:24:14   作者:crossoverJie  
這篇文章主要為大家介紹了剖析SpringCloud Feign中所隱藏的坑示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

背景

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

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

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

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

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

想法很簡(jiǎn)單,但實(shí)踐起來卻不是那么回事了。 偽代碼如下:

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

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

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

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

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

Debug

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

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

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

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

既然是 url 有值就能正常運(yùn)行,那一定是在運(yùn)行過程中獲取了這個(gè)值;

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

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

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

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

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

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

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

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

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

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

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

Feign 的實(shí)現(xiàn)

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

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

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

畢竟使用 java.net.URI 的場(chǎng)景也不會(huì)太多。

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

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

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

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

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

總結(jié)

其實(shí)本文重點(diǎn)是分析了一些 debug 和閱讀源碼的一些小技巧,特別是在讀關(guān)于 Spring 相關(guān)的代碼時(shí)一定不能 debug 跟蹤到細(xì)節(jié)中,因?yàn)檎{(diào)用鏈通常是很長(zhǎng)的,稍不留神就把自己都繞暈了,只需要知道核心、關(guān)鍵源碼是如何處理的即可。

最后對(duì)于 OpenFeign 處理動(dòng)態(tài) url 的方案確實(shí)也有些疑惑,是一個(gè)典型的約定大于配置的場(chǎng)景,但問題就在于我們并不知道這個(gè)約定是 @Feign 的 url 得有值。

所以我也提了一個(gè) PROpenFeign,感興趣的朋友也可以查看一下:

github.com/spring-clou…

以上就是剖析SpringCloud Feign中所隱藏的坑的詳細(xì)內(nèi)容,更多關(guān)于SpringCloud Feign坑的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析Java.IO輸入輸出流 過濾流 buffer流和data流

    淺析Java.IO輸入輸出流 過濾流 buffer流和data流

    這篇文章主要介紹了Java.IO輸入輸出流 過濾流 buffer流和data流的相關(guān)資料,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-10-10
  • Mybatis 將table表名作為參數(shù)傳入操作

    Mybatis 將table表名作為參數(shù)傳入操作

    這篇文章主要介紹了Mybatis 將table表名作為參數(shù)傳入操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 2021年最新Redis面試題匯總(3)

    2021年最新Redis面試題匯總(3)

    在程序員面試過程中redis相關(guān)的知識(shí)是常被問到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下
    2021-07-07
  • springmvc參數(shù)為對(duì)象,數(shù)組的操作

    springmvc參數(shù)為對(duì)象,數(shù)組的操作

    這篇文章主要介紹了springmvc參數(shù)為對(duì)象,數(shù)組的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    這篇文章主要介紹了SpringBoot中Shiro緩存使用Redis、Ehcache的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java8 HashMap的實(shí)現(xiàn)原理分析

    Java8 HashMap的實(shí)現(xiàn)原理分析

    Java8之后新增挺多新東西,接下來通過本文給大家介紹Java8 HashMap的實(shí)現(xiàn)原理分析,對(duì)java8 hashmap實(shí)現(xiàn)原理相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-03-03
  • springIoc及注解的使用實(shí)例詳解

    springIoc及注解的使用實(shí)例詳解

    注解(Annotation)是一種在 Java 程序中以元數(shù)據(jù)的形式對(duì)代碼進(jìn)行標(biāo)記和說明的機(jī)制,它可以被添加到類、方法、字段、參數(shù)等程序元素上,用于提供額外的信息和指示,本文給大家介紹springIoc及注解的使用,感興趣的朋友一起看看吧
    2024-02-02
  • 詳解Java修飾符

    詳解Java修飾符

    Java語言提供了很多修飾符,主要分為以下兩類:訪問修飾符;非訪問修飾符。修飾符用來定義類、方法或者變量,通常放在語句的最前端。我們通過下面的例子來說明,下面就跟小編一起來看下吧
    2016-12-12
  • SpringBoot動(dòng)態(tài)更新yml文件

    SpringBoot動(dòng)態(tài)更新yml文件

    在系統(tǒng)運(yùn)行過程中,可能由于一些配置項(xiàng)的簡(jiǎn)單變動(dòng)需要重新打包啟停項(xiàng)目,這對(duì)于在運(yùn)行中的項(xiàng)目會(huì)造成數(shù)據(jù)丟失,客戶操作無響應(yīng)等情況發(fā)生,針對(duì)這類情況對(duì)開發(fā)框架進(jìn)行升級(jí)提供yml文件實(shí)時(shí)修改更新功能,這篇文章主要介紹了SpringBoot動(dòng)態(tài)更新yml文件
    2023-01-01
  • java程序中的延時(shí)加載異常及解決方案

    java程序中的延時(shí)加載異常及解決方案

    這篇文章主要介紹了java程序中的延時(shí)加載異常及解決方案,需要的朋友可以參考下
    2015-02-02

最新評(píng)論