git地址
https://github.com/a18792721831/studySpringCloud.git
1. Feign工作原理
項目需要集成Feign,那麼就需要在main方法對應的類上加上Feign開啓的註解@EnableFeignClients
進入@EnableFeignClients註解
FeignClientsRegistrar
會進行一些處理
Feign 通過包掃描注入 FeignClient 的 Bean,該源碼在FeignClientsRegistrar類中。首先在程序啓動時,會檢查是否有@EnableFeignClients註解,如果有該註解,則開啓包掃描,掃描被@FeignClient 註解的接口。
通過斷點調試,當程序的啓動類上有@EnablefeignClients 註解。在程序啓動後,程序會通過包掃描將有
@FegaClient註解修飾的接口連同接口名和註解的信息一起取出,賦給 BeanDefinitionBuilde然後根據BeanDefnitionBuilder 得到BeanDefinition,最後將 BeanDefinition 注入IoC 容器中。
注入BeanDefinition之後,通過JDK的代理,當調用Feign Cleint接口裏面的方法時,該方法會被攔截。
在SynchronousMethodHandler類進行攔截處理,會根據參數生成RequestTemplate對象,該對象是Http請求的模板。
executeAndDecode方法通過RequestTemplate生成Reques請求對象,然後用Http Client獲取Rqsponse,即通過Http Client進行Http請求獲取響應。
2. Feign使用HttpClient和OkHttp
首先查看FeignRibbonClient的自動配置類,該類在工程啓動時注入一些Bean,其中注入了一個BeanName爲FeignClient的Bean
在缺省配置BeanName爲FeignClient的Bean的情況下,會自動注入Client.Default這個對象。
我們剛纔看了默認的配置,上面之前Import還有其他兩個類
這是HttpClient
發現代碼提示異常,是ApacheHttpClient的依賴未找到。
所以,只需要我們加入這個依賴就能使用HttpClient作爲Feign的請求。
從@ConditionalOnProperty中看出,需要在配置文件將feign.httpclient.enabled設置爲true.當然,也可以不寫,默認爲true
接下來看OkHttp
OkHttp上面的註解就沒有默認值了,所以OkHttp就需要配置了,
因爲默認是false.
3. Feign是如何實現負載均衡
當程序的啓動類上有@EnablefeignClients 註解。在程序啓動後,程序會通過包掃描將有@FegaClient註解修飾的接口連同接口名和註解的信息一起取出,賦給 BeanDefinitionBuilde然後根據BeanDefnitionBuilder 得到BeanDefinition,最後將 BeanDefinition 注入IoC 容器中。
其中有一個executeWithLoadBalancer方法,通過負載均衡的方式執行網絡請求。
進入commit方法,,內部是LoadBalancerCommand的方法
selectServer方法就是選擇服務進行負載均衡
到了這裏,又到了RibbonLoadBalancer的loadBalancerContext進行處理,即交由Ribbon進行處理了。
總的來說,Feign的源碼實現過程如下。
- (1)首先通過@EnableFeignClients 註解開啓 FeignClient的功能。只有這個註解存在,纔會在程序啓動時開啓對@FeignClient註解的包掃描。
- (2)根據Feign的規則實現接口,並在接口上面加上@FcignClient註解。
- (3)程序啓動後,會進行包掃描,掃描所有的@ FeignClient 的註解的類,並將這些信息注入IoC 容器中。
- (4)當接口的方法被調用時,通過JDK 的代理來生成具體的 RequestTemplate 模板對象。
- (5)根據 RequestTemplate 再生成 Http 請求的 Request對象。
- (6)Request 對象交給 Client 去處理,其中 Client 的網絡請求框架可以是 HttpURLConnection、HttpClient 和 OkHttp。
- (7)最後Client被封裝到LoadBalanceClient類,這個類結合類Ribbon做到了負載均衡。