摘要:內(nèi)部使用了的動態(tài)代理為目標接口生成了一個動態(tài)代理類,這里會生成一個動態(tài)代理原理統(tǒng)一的方法攔截器,同時為接口的每個方法生成一個攔截器,并解析方法上的元數(shù)據(jù),生成一個請求模板。的核心源碼解析到此結(jié)束了,不知道是否對您有無幫助,可留言跟我交流。
Feign是一個聲明式的Web服務(wù)客戶端。這使得Web服務(wù)客戶端的寫入更加方便 要使用Feign創(chuàng)建一個界面并對其進行注釋。它具有可插拔注釋支持,包括Feign注釋和JAX-RS注釋。Feign還支持可插拔編碼器和解碼器。Spring Cloud添加了對Spring MVC注釋的支持,并在Spring Web中使用默認使用的HttpMessageConverters。Spring Cloud集成Ribbon和Eureka以在使用Feign時提供負載均衡的http客戶端。
在介紹spring cloud feign之前,先來看看原生的feign,然后在看spring cloud feign是怎么樣集成原生的feign的。
一、原生的feign的用法
1、引入jar
io.github.openfeign feign-gson 9.5.0
2、編寫代碼,以下是發(fā)送GET和POST請求方式(更多請查看)
public class FeignTest { interface BookService{ @RequestLine("GET /book/borrow?name={name}&timeout={timeout}") String borrow(@Param("name")String name,@Param("timeout")Integer timeout); @RequestLine("POST /book/post") @Headers("Content-Type: application/json") @Body("%7B"id": "{id}", "name": "{name}"%7D") String post(@Param("id")String id,@Param("name")String name); } public static void main(String[] args) { BookService bs = Feign.builder() .options(new Options(2000, 6000)) .target(BookService.class, "http://localhost:2001"); String result = bs.borrow("2w2w",1); System.out.println(result); result = bs.post("12345", "spring feign"); System.out.println(result); } }
feign核心類介紹
feign.Feign.Builder 設(shè)置發(fā)送http請求的相關(guān)參數(shù),比如http客戶端,重試策略,編解碼,超時時間等等
feign.Contract.Default 解析接口方法的元數(shù)據(jù),構(gòu)建http請求模板
feign.Client 發(fā)送http請求客戶端,默認實現(xiàn)feign.Client.Default,使用的是java.net包實現(xiàn)的
Retryer 重試,默認實現(xiàn)feign.Retryer.Default,超時延遲100ms開始重試,每隔1s重試一次,重試4次
Options 超時時間,默認連接超時10s,讀超時60s
feign.codec.Encoder 編碼器
feign.codec.Decoder 解碼器
RequestInterceptor 請求攔截器,可以在發(fā)送http請求之前執(zhí)行此攔截器
feign.Contract 接口以及方法元數(shù)據(jù)解析器
以上參數(shù)都可以自己擴展
HardCodedTarget 定于目標接口和url
ReflectiveFeign 生成動態(tài)代理類,基于jdk的動態(tài)代理實現(xiàn)
feign.InvocationHandlerFactory.Default 接口方法統(tǒng)一攔截器創(chuàng)建工廠
FeignInvocationHandler 接口統(tǒng)一方法攔截器
ParseHandlersByName 解析接口方法元數(shù)據(jù)
SynchronousMethodHandler.Factory 接口方法的攔截器創(chuàng)建工廠
SynchronousMethodHandler 接口方法的攔截器,真正攔截的核心,這里真正發(fā)起http請求,處理返回結(jié)果
在上述示例代碼中,到底feign給我做了哪些事情呢?下面的時序圖為我們展示整個處理過程
1、通過feign.Feign.Builder為我們設(shè)置http請求的相關(guān)參數(shù),比如http客戶端,重試策略,編解碼,超時時間,這里都是面向接口編程實現(xiàn)的,我們很容易的進行擴展,比如http客戶端,可以使用java原生的實現(xiàn),也可以使用apache httpclient,亦可以使用okHttpClient,自己喜歡就好,其他屬性亦是如此,由此看出feign的設(shè)計具有非常好的可擴展性。
2、ReflectiveFeign內(nèi)部使用了jdk的動態(tài)代理為目標接口生成了一個動態(tài)代理類,這里會生成一個InvocationHandler(jdk動態(tài)代理原理)統(tǒng)一的方法攔截器,同時為接口的每個方法生成一個SynchronousMethodHandler攔截器,并解析方法上的 元數(shù)據(jù),生成一個http請求模板。
3、當發(fā)起方法調(diào)用的時候,被統(tǒng)一的方法攔截器FeignInvocationHandler攔截,再根據(jù)不同的方法委托給不同的SynchronousMethodHandler攔截器處理。
4、根據(jù)每次方法調(diào)用的入?yún)⑸蒱ttp請求模板,如果設(shè)置了http請求攔截器,則先經(jīng)歷攔截器的處理,再發(fā)起真正的http請求,得到結(jié)果后會根據(jù)方法放入返回值進行反序列化,最后返回給調(diào)用方。
5、如果發(fā)生了異常,會根據(jù)重試策略進行重試。
feign也整合了Hystrix,實現(xiàn)熔斷降級的功能,其實也很簡單,上面的分析我們知道了feign在方法調(diào)用的時候會經(jīng)過統(tǒng)一方法攔截器FeignInvocationHandler的處理,而HystrixFeign則是使用了HystrixInvocationHandler代替,在方法調(diào)用的時候進行Hystrix的封裝,這里需要特別說明下:
Hystrix有超時時間,feign本身也有超時時間,正常來說Hystrix的超時間要大于feign的超時時間,如果是小于的話,Hytrix已經(jīng)超時了,feign再等待就已經(jīng)沒有意義了。
再則就是feign超時的話會觸發(fā)重試操作,此時要是Hytrix發(fā)生超時異常返回了,但這并不會切斷feign的繼續(xù)操作,什么意思呢?假設(shè)Hytrix的超時時間為1s,feign設(shè)置的超時時間為2s,而真正業(yè)務(wù)操作需要耗時3s,這時Hytrix超時異常返回,而后feign也會發(fā)生超時異常,但是feign會根據(jù)超時策略繼續(xù)進行重試操作,并不會因為Hytrix的中斷而中斷。所以Hytrix的超時時間一般要大于feign的總超時時間,如這個例子中要設(shè)置2 5(默認重試次數(shù)4 + 1)=10s,公式就是Hytrix的超時間=feign的超時 時間 (feign的重試次數(shù) + 1)
以上就是原生feign的基本原理,下面我們來分析下springcloud是如何進行整合進來的,又添加了一些什么東西?
spring-cloud-feign的基本用法:
1、開啟注解EnableFeignClients
@EnableFeignClients public class ApplicationStartup { public static void main(String[] args) { SpringApplication.run(ApplicationStartup.class, args); } }
2、定義接口
@FeignClient(name = "user") public interface IUserService{ @RequestMapping(value = "/api/getUser") User getUser(Long id); }
3、這樣通過spring注入IUserService就可以使用了
@Controller public class UserController { @Autowired private IUserService userService; }
使用起來非常簡單,核心的兩步就是開啟注解,定于feignclient接口。
一、開啟@EnableFeignClients注解到底給我們做了什么事情呢?
1、掃描EnableFeignClients注解上的配置信息,注冊默認的配置類,這個配置類是對所有feignclient的都是生效的,即為全局的配置。
2、掃描帶有@FeignClient注解的接口,并注冊配置類(此時的配置類針對當前feignclient生效)和FeignClientFactoryBean,此bean實現(xiàn)了FactoryBean接口,我們知道spring有兩種類型的bean對象,一種是普通的bean,另一種則是工廠bean(FactoryBean),它返回的其實是getObject方法返回的對象(更多關(guān)于FactoryBean的相關(guān)信息請查看spring官方文檔)。getObject方法就是集成原生feign的核心方法,當spring注入feignclient接口時,getObject方法會被調(diào)用,得到接口的代理類。
備注:在FeignClient指定配置類時,切記不要被spring容器掃描到,不然會對全局生效。
二、自動加載配置類FeignAutoConfiguration,F(xiàn)eignClientsConfiguration,F(xiàn)eignRibbonClientAutoConfiguration,這三個類為feign提供了所有的配置類,默認情況下所加載的類情況:
feign.Feign.Builder 當引入了Hytrix并開啟參數(shù)feign.hystrix.enabled=true后,則會加載feign.hystrix.HystrixFeign.Builder,此時feign就具備降級熔斷的功能了。
feign.Client 此實現(xiàn)類的加載分兩種情況:
使用url方式:feign.Client.Default,使用java原生的方式(java.net包)發(fā)起http請求,也可以自己擴展。
使用name方式:LoadBalancerFeignClient,集成了ribbon,實現(xiàn)服務(wù)發(fā)現(xiàn)與負載均衡,但是真正發(fā)起http請求還是java原生的方式
此處是一擴展點,當我們引入ApacheHttpClient時,http客戶端就會使用apache的httpClient;當我們引入OkHttpClient時,http客戶端就會使用okhttp3.OkHttpClient。
feign.Retryer 默認Retryer.NEVER_RETRY,不進行重試,這里也可以自己實現(xiàn)Retryer接口實現(xiàn)自己的重試策略,但是feign在集成了ribbon的情況下,最好保持默認不進行重試,因為ribbon也會有重試策略,如果feign也開啟重試,容易產(chǎn)生混亂;其實在低版本中spring-cloud-feing重試默認并不是NEVER_RETRY,可能spring-cloud-feing也意識到這樣做的問題,所以在D版中改成NEVER_RETRY了。
feign.Request.Options 默認設(shè)置連接超時時間是10,讀超時時間是60s。這里也可以更改,分兩種情況:
使用url方式:必須通過這個參數(shù)來設(shè)置,才生效
@Configuration public class MyConfig { @Bean public Request.Options options(){ Request.Options o = new Options(1000, 1000); return o; } }
然后在注解上@FeignClient指定:
@FeignClient(name="",url="",configuration= {MyConfig.class})
注意此類不能被spring容器掃描到,否則會對全局生效。你也可以通過注解@EnableFeignClients來全局指定:
@EnableFeignClients(defaultConfiguration=MyConfig.class)
使用name方式:此時已經(jīng)集成了ribbon,可以使用以下配置來設(shè)置,如果你此時也配置了Options,以下配置會被覆蓋
# 對所有的feignclient生效 ribbon.ReadTimeout=10000 ribbon.ConnectTimeout=2000 # 對指定的feignclien生效 [feignclientName].ribbon.ReadTimeout=10000 [feignclientName].ribbon.ConnectTimeout=2000
如果開啟Hytrix,hytrix也有超時時間設(shè)置,但是hytrix是封裝在feign基礎(chǔ)之上的,上文已有分析。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
你也可以關(guān)閉hytrix的超時時間
hystrix.command.default.execution.timeout.enabled=false
feign.codec.Decoder 解碼器,默認使用了HttpMessageConverters來實現(xiàn)
feign.codec.Encoder 編碼器,默認使用了HttpMessageConverters來實現(xiàn)
feign.Contract 默認提供springmvc的注解解析,支持@RequestMapping,@RequestBody,@RequestParam,@PathVariable
最后三種也是spring-cloud-feign替換原生feign的默認實現(xiàn),對springMVC的相關(guān)支持,會另有文章進行解析。
spring-cloud-feign的核心源碼解析到此結(jié)束了,不知道是否對您有無幫助,可留言跟我交流。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69474.html
摘要:一簡介是一個聲明式的服務(wù)客戶端,它使得寫服務(wù)變得更簡單。同時支持可插拔的編碼器和解碼器。對添加了支持,同時在中次用相同的。 轉(zhuǎn)載請標明出處: http://blog.csdn.net/forezp/a...本文出自方志朋的博客 上一篇文章,講述了通過restTemplate+ribbon去消費服務(wù),這篇文章主要講述通過feign去消費服務(wù)。 一、Feign簡介 Feign是一個聲明式的...
摘要:機制博客從到學習介紹從到學習上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學習配置文件詳解從到學習介紹從到學習如何自定義從到學習介紹從到學習如何自定義從到學習轉(zhuǎn)換從到學習介紹中的從到學習中的幾種詳解從到學習讀取數(shù)據(jù)寫入到從到學習項目如何運行從 Flink Checkpoint 機制 https://t.zsxq.com/ynQNbeM 博客 1、Flink 從0到1學習 —— Apache Fl...
摘要:序列化機制博客從到學習介紹從到學習上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學習配置文件詳解從到學習介紹從到學習如何自定義從到學習介紹從到學習如何自定義從到學習轉(zhuǎn)換從到學習介紹中的從到學習中的幾種詳解從到學習讀取數(shù)據(jù)寫入到從到學習項目如何 Flink 序列化機制 https://t.zsxq.com/JaQfeMf 博客 1、Flink 從0到1學習 —— Apache Flink 介紹 2...
摘要:模塊中的類結(jié)構(gòu)如下博客從到學習介紹從到學習上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學習配置文件詳解從到學習介紹從到學習如何自定義從到學習介紹從到學習如何自定義從到學習轉(zhuǎn)換從到學習介紹中的從到學習中的幾種詳解從到學習讀取數(shù)據(jù)寫入到從到學 Flink-Client 模塊中的類結(jié)構(gòu)如下: https://t.zsxq.com/IMzNZjY showImg(https://segmentfau...
摘要:模塊中的類結(jié)構(gòu)如下博客從到學習介紹從到學習上搭建環(huán)境并構(gòu)建運行簡單程序入門從到學習配置文件詳解從到學習介紹從到學習如何自定義從到學習介紹從到學習如何自定義從到學習轉(zhuǎn)換從到學習介紹中的從到學習中的幾種詳解從到學習讀取數(shù)據(jù)寫入到從到學 Flink-Annotations 模塊中的類結(jié)構(gòu)如下: https://t.zsxq.com/f6eAu3J showImg(https://segme...
閱讀 1125·2021-11-24 10:21
閱讀 2561·2021-11-19 11:35
閱讀 1662·2019-08-30 15:55
閱讀 1293·2019-08-30 15:54
閱讀 1192·2019-08-30 15:53
閱讀 3498·2019-08-29 17:21
閱讀 3308·2019-08-29 16:12
閱讀 3412·2019-08-29 15:23