2 萬字好文全方位深刻學習 SpringCloud Fegin,讓面試再也不彷徨

首發地址:2萬字好文全方位深刻學習SpringCloud Fegin,面試不在彷徨javascript

與Fegin相遇以前 

在咱們平時的工做中,咱們常常會遇到要調用內部API或者其餘第三方服務的API,在遇到Fegin以前咱們基本會使用如下幾種方式。java

1.HttpURLConnectiongit

簡介:github

URLConnection是個抽象類,它有兩個直接子類分別是HttpURLConnection和JarURLConnection。web

另一個重要的類是URL,一般URL能夠經過傳給構造器一個String類型的參數來生成一個指向特定地址的URL實例。
每一個 HttpURLConnection 實例均可用於生成單個請求,可是其餘實例能夠透明地共享鏈接到 HTTP 服務器的基礎網絡。面試

請求後在 HttpURLConnection 的 InputStream 或 OutputStream 上調用 close() 方法能夠釋放與此實例關聯的網絡資源,但對共享的持久鏈接沒有任何影響。spring

若是在調用 disconnect() 時持久鏈接空閒,則可能關閉基礎套接字。express

任何網絡鏈接都須要通過socket才能鏈接,HttpURLConnection不須要設置socket,因此,HttpURLConnection並非底層的鏈接,而是在底層鏈接上的一個請求編程

這就是爲何HttpURLConneciton只是一個抽象類,自身不能被實例化的緣由。HttpURLConnection只能經過URL.openConnection()方法建立具體的實例。json

雖然底層的網絡鏈接能夠被多個HttpURLConnection實例共享,但每個HttpURLConnection實例只能發送一個請求。

請求結束以後,應該調用HttpURLConnection實例的InputStream或OutputStream的close()方法以釋放請求的網絡資源,不過這種方式對於持久化鏈接沒用。對於持久化鏈接,得用disconnect()方法關閉底層鏈接的socket。

HttpURLConnection請求響應流程:

2.HttpClient

簡介:

HttpClient是Apache Jakarta Common 下的子項目,能夠用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,而且它支持 HTTP 協議最新的版本和建議。


它是一個HTTP通訊庫、一個工具包,所以它只提供一個通用瀏覽器應用程序所指望的功能子集。


HttpClient與瀏覽器最根本的區別是:HttpClient中沒有用戶界面,瀏覽器須要一個渲染引擎來顯示頁面,並解釋用戶輸入(例如鼠標點擊顯示頁面上的某處以後如何響應、計算如何顯示HTML頁面、級聯樣式表和圖像、javascript解釋器運行嵌入HTML頁面或從HTML頁面引用的javascript代碼、來自用戶界面的事件被傳遞到javascript解釋器進行處理等等等等)。


HttpClient只能以編程的方式經過其API用於傳輸和接受HTTP消息,它對內容也是徹底不可知的。

HttpClient仍是有不少好的特色(摘自Apache HttpClient官網)

1.基於標準、純淨的java語言。實現了HTTP1.0和HTTP1.1;

2.以可擴展的面向對象的結構實現了HTTP所有的方法(GET, POST等7種方法);

3.支持HTTPS協議;

4.經過HTTP代理創建透明的鏈接;

5.利用CONNECT方法經過HTTP代理創建隧道的HTTPS鏈接;

6.Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos認證方案;

7.插件式的自定義認證方案;

8.便攜可靠的套接字工廠使它更容易的使用第三方解決方案;

9.鏈接管理器支持多線程應用;支持設置最大鏈接數,同時支持設置每一個主機的最大鏈接數,發現並關閉過時的鏈接;

10.自動處理Set-Cookie中的Cookie;

11.插件式的自定義Cookie策略;

12.Request的輸出流能夠避免流中內容直接緩衝到socket服務器;

13.Response的輸入流能夠有效的從socket服務器直接讀取相應內容;

14.在HTTP1.0和HTTP1.1中利用KeepAlive保持持久鏈接;

15.直接獲取服務器發送的response code和 headers;

16.設置鏈接超時的能力;

17.實驗性的支持HTTP1.1 response caching;

18.源代碼基於Apache License 可免費獲取。

Get Demo

public static void main(String[] args) throws IOException { //1.打開瀏覽器 CloseableHttpClient httpClient = HttpClients.createDefault(); //2.聲明get請求 HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java"); //3.發送請求 CloseableHttpResponse response = httpClient.execute(httpGet); //4.判斷狀態碼 if(response.getStatusLine().getStatusCode()==200){ HttpEntity entity = response.getEntity(); //使用工具類EntityUtils,從響應中取出實體表示的內容並轉換成字符串 String string = EntityUtils.toString(entity, "utf-8"); System.out.println(string); } //5.關閉資源 response.close(); httpClient.close(); }

Post Demo





public static void main(String[] args) throws IOException { //1.打開瀏覽器 CloseableHttpClient httpClient = HttpClients.createDefault(); //2.聲明get請求 HttpPost httpPost = new HttpPost("https://www.oschina.net/"); //3.開源中國爲了安全,防止惡意攻擊,在post請求中都限制了瀏覽器才能訪問 httpPost.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"); //4.判斷狀態碼 List<NameValuePair> parameters = new ArrayList<NameValuePair>(0); parameters.add(new BasicNameValuePair("scope", "project")); parameters.add(new BasicNameValuePair("q", "java")); UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters,"UTF-8"); httpPost.setEntity(formEntity); //5.發送請求 CloseableHttpResponse response = httpClient.execute(httpPost); if(response.getStatusLine().getStatusCode()==200){ HttpEntity entity = response.getEntity(); String string = EntityUtils.toString(entity, "utf-8"); System.out.println(string); } //6.關閉資源 response.close(); httpClient.close(); }

3.OKHttp

給你們推薦一篇文章,我的以爲寫得很好。

https://blog.csdn.net/iispring/article/details/51661195?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param

4.RestTemplate

簡介:

RestTemplate 是從 Spring3.0 開始支持的一個 HTTP 請求工具,它提供了常見的REST請求方案的模版,例如 GET 請求、POST 請求、PUT 請求、DELETE 請求以及一些通用的請求執行方法 exchange 以及 execute。

RestTemplate 繼承自 InterceptingHttpAccessor 而且實現了 RestOperations 接口,其中 RestOperations 接口定義了基本的 RESTful 操做,這些操做在 RestTemplate 中都獲得了實現。接下來咱們就來看看這些操做方法的使用。

Get Demo

public void doHttpGetTest() throws UnsupportedEncodingException { // -------------------------------> 獲取Rest客戶端實例 RestTemplate restTemplate = new RestTemplate();  // -------------------------------> 解決(響應數據可能)中文亂碼 的問題 List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters(); converterList.remove(1); // 移除原來的轉換器 // 設置字符編碼爲utf-8 HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); converterList.add(1, converter); // 添加新的轉換器(注:convert順序錯誤會致使失敗) restTemplate.setMessageConverters(converterList);  // -------------------------------> (選擇性設置)請求頭信息 // HttpHeaders實現了MultiValueMap接口 HttpHeaders httpHeaders = new HttpHeaders(); // 給請求header中添加一些數據    httpHeaders.add("Java 學習部落""這是一個學習技術的公衆號!");  // -------------------------------> 注:GET請求 建立HttpEntity時,請求體傳入null便可 // 請求體的類型任選便可;只要保證 請求體 的類型與HttpEntity類的泛型保持一致便可 String httpBody = null; HttpEntity<String> httpEntity = new HttpEntity<String>(httpBody, httpHeaders);  // -------------------------------> URI StringBuffer paramsURL = new StringBuffer("http://127.0.0.1:8080/restTemplate/doHttpGet"); // 字符數據最好encoding一下;這樣一來,某些特殊字符才能傳過去(如:flag的參數值就是「&」,不encoding的話,傳不過去) paramsURL.append("?flag=" + URLEncoder.encode("&", "utf-8")); URI uri = URI.create(paramsURL.toString());  // -------------------------------> 執行請求並返回結果 // 此處的泛型 對應 響應體數據 類型;    // 即:這裏指定響應體的數據裝配爲String ResponseEntity<String> response =  restTemplate.exchange(uri, HttpMethod.GET, httpEntity, String.class);  // -------------------------------> 響應信息 //響應碼,如:40一、30二、40四、500、200等 System.err.println(response.getStatusCodeValue()); Gson gson = new Gson(); // 響應頭 System.err.println(gson.toJson(response.getHeaders())); // 響應體 if(response.hasBody()) { System.err.println(response.getBody()); }  }

 

Post Demo

public void doHttpPostTest() throws UnsupportedEncodingException { // 獲取Rest客戶端實例 RestTemplate restTemplate = new RestTemplate();   //  解決(響應數據可能)中文亂碼 的問題 List<HttpMessageConverter<?>> converterList  = restTemplate.getMessageConverters(); converterList.remove(1); // 移除原來的轉換器 // 設置字符編碼爲utf-8 HttpMessageConverter<?> converter  = new StringHttpMessageConverter(StandardCharsets.UTF_8); // 添加新的轉換器(注:convert順序錯誤會致使失敗) converterList.add(1, converter);  restTemplate.setMessageConverters(converterList);  // (選擇性設置)請求頭信息 // HttpHeaders實現了MultiValueMap接口 HttpHeaders httpHeaders = new HttpHeaders(); // 設置contentType httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); // 給請求header中添加一些數據  httpHeaders.add("Java 學習部落""這是一個學習java的公衆號 !");  // 將請求頭、請求體數據,放入HttpEntity中 // 請求體的類型任選便可;只要保證 請求體 的類型與HttpEntity類的泛型保持一致便可 // 這裏手寫了一個json串做爲請求體 數據 (實際開發時,可以使用fastjson、gson等工具將數據轉化爲json串)  String httpBody = "{\"motto\":\"java真強大啊 !\"}"; HttpEntity<String> httpEntity  = new HttpEntity<String>(httpBody, httpHeaders);   // URI StringBuffer paramsURL  = new StringBuffer("http://127.0.0.1:8080/restTemplate/doHttpPost"); // 字符數據最好encoding一下;這樣一來,某些特殊字符才能傳過去(如:flag的參數值就是「&」,不encoding的話,傳不過去) paramsURL.append("?flag=" + URLEncoder.encode("&", "utf-8")); URI uri = URI.create(paramsURL.toString());  // 執行請求並返回結果 // 此處的泛型 對應 響應體數據 類型;即:這裏指定響應體的數據裝配爲String ResponseEntity<String> response =  restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);  // 響應信息 //響應碼,如:40一、30二、40四、500、200等 System.err.println(response.getStatusCodeValue()); Gson gson = new Gson(); // 響應頭 System.err.println(gson.toJson(response.getHeaders())); // 響應體 if(response.hasBody()) { System.err.println(response.getBody());  }}

此處只是簡單介紹下RestTemplate的Get請求和Post請求,並未深刻探討RestTemplate,以及實現RestTemplate的其它形式的請求。

由於我已經火燒眉毛的想和Fegin來一個美麗的邂逅了。

與Fegin的美麗邂逅

什麼是Fegin?

Feign是Netflix開發的聲明式、模板化的HTTP客戶端, Feign能夠幫助咱們更快捷、優雅地調用HTTP API。

在Spring Cloud中,使用Feign很是簡單:建立一個接口,並在接口上添加一些註解,代碼就完成了。Feign支持多種註解,例如Feign自帶的註解或者JAX-RS註解等。

Spring Cloud對Feign進行了加強,使Feign支持了Spring MVC註解,並整合了Ribbon和Eureka,從而讓Feign的使用更加方便。

Spring Cloud Feign是基於Netflix feign實現,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供這二者的強大功能外,還提供了一種聲明式的Web服務客戶端定義的方式。

Spring Cloud Feign幫助咱們定義和實現依賴服務接口的定義。在Spring Cloud feign的實現下,只須要建立一個接口並用註解方式配置它,便可完成服務提供方的接口綁定,簡化了在使用Spring Cloud Ribbon時自行封裝服務調用客戶端的開發量。

Spring Cloud Feign具有可插拔的註解支持,支持Feign註解、JAX-RS註解和Spring MVC的註解。

Feign其實是對普通HTTP客戶端的一層封裝,其目的是下降集成成本、提高可靠性。Feign支持三種HTTP客戶端,包括JDK自帶的HttpURLConnection、Apache HttpClient和Square OkHttp,默認使用Apache HttpClient。

Fegin有什麼做用?

Feign能夠把Rest的請求進行隱藏,假裝成相似SpringMVC的Controller同樣。

你不用再本身拼接url,拼接參數等等操做,一切都交給Feign去作。

Netflix Feign仍是Open Feign?

在這個時間節點上,不少人對這「兩種」Feign傻傻分不清楚,不知有何區別和聯繫,本文將給與告知。首先須要明確:他倆是屬於同一個東西,Feign屬於Netflix開源的組件。針對於於差別性,下面分這幾個方面展開作出對比

一、GAV座標差別

<dependency>
    <groupId>com.netflix.feign</groupId>
    <artifactId>feign-core</artifactId>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
</dependency>

二、官網地址差別https://github.com/Netflix/feignhttps://github.com/OpenFeign/feign。不過如今訪問https://github.com/Netflix/feign已經被重定向到了後者上。

三、發版歷史

  • Netflix Feign1.0.0發佈於2013.6,於2016.7月發佈其最後一個版本8.18.0

  • Open Feign:首個版本即是9.0.0版,於2016.7月發佈,而後一直持續發佈到如今(未中止)

從以上3個特色其實你能夠很清楚的看到二者的區別和聯繫,簡單的理解:Netflix Feign僅僅只是更名成爲了Open Feign而已,而後Open Feign項目在其基礎上繼續發展至今。

9.0版本以前它叫Netflix Feign,自9.0版本起它更名叫Open Feign了。

可是請注意,雖然GAV徹底變了,可是源碼的包名和核心API是沒有任何變化的,因此扔具備很好的向下兼容性(並非100%向下兼容)。

spring-cloud-starter-feign仍是spring-cloud-starter-openfeign?

他倆的差別相似於上述描述的差別,也從幾個方面說明:

一、GAV座標差別

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

發版歷史

  • spring-cloud-starter-feign:2015.3發佈1.0.0版本,2019.5.23發佈器最後一個版本1.4.7.RELEASE

    • 值得注意的是,從1.4.0.RELEASE開始,它的1.4.x的發版軌跡徹底同下的1.4.x的發版軌跡

  • spring-cloud-starter-openfeign:2017.11發佈其首個版本,版本號爲:1.4.0.RELEASE。如今仍持續更新中,當下最新版爲2.2.1.RELEASE

說明:1.4.7.RELEASE是整個Spring Cloud1.x關於Feign方面的最終版本,2.x版本還在持續維護更新中

注意:老的spring-cloud-starter-feign 1.2.0.RELEASE開始 已放棄Netflix feign而全面使用更新的Open Feign版本,而spring-cloud-starter-openfeign更是和Netflix Feign已經沒有關係了。

對於版本,可粗略的理解爲:spring-cloud-starter-openfeign是爲Spring Cloud2.x準備的,只不過維持了一段時間的對1.x的兼容。而spring-cloud-starter-feign是專爲Spring Cloud1.x服務。

核心API包名:Spring Cloud的大版本升級具備向下不兼容性,這也體如今了Feign上:

@FeignClient註解:

說明:這裏的1.x不只僅指的feign,還包括openfeign的1.4.x版本哦

1.x版本包名是org.springframework.cloud.netflix.feign.FeignClient,所在Jar是spring-cloud-netflix-core

2.x版本包名是org.springframework.cloud.openfeign.FeignClient,所在Jar是spring-cloud-openfeign-core

@EnableFeignClients註解:差別同上

 

 

 

 

 

 

                                                                   

                                                                    

 

 

 

 

 

 

 ----引自:https://cloud.tencent.com/developer/article/1588509


與Fegin的相知相識

Fegin 的九大組件

1.註解翻譯器 Contract 

咱們都知道,在 Feign 中能夠經過定義 API 接口的方式來調用遠程的 Http API,在定義調用 Client 的時候須要增長一些註解來描述這個調用 API 的基本信息,好比請求類型是 GET 仍是 POST,請求的 URI 是什麼。

Contract 容許用戶自定義註解翻譯器去解析註解信息。

Contract 決定了哪些註解能夠標註在接口/接口方法上是有效的,而且提取出有效的信息,組裝成爲MethodMetadata元信息。

最典型的應用場景就是在 Spring Cloud 中使用 Feign,咱們可使用 Spring MVC 的註解來定義 Feign 的客戶端,就是由於 Spring Cloud OpenFeign 中實現了本身的 SpringMvcContract。

2.Encoder 編碼器

將咱們的請求信息經過指定的編碼方式進行編碼到Http請求體中進行傳輸。

3.QueryMapEncoder 參數查詢編碼器

QueryMapEncoder 是針對實體類參數查詢的編碼器,能夠基於 QueryMapEncoder 將實體類生成對應的查詢參數。

4.Decoder 解碼器

Decoder 解碼器做用於Response,用於解析Http請求的響應,提取有用信息數據。

Decoder 解碼器將HTTP響應feign.Response解碼爲指定類型的單一對象

5.ErrorDecoder 錯誤解碼器

ErrorDecoder 錯誤解碼器是在發生錯誤、異常狀況時使用的解碼器,容許你對異常進行特殊處理。

6.Logger 日誌記錄

Feign本身抽象出來的一個日誌記錄器,負責 Feign 中記錄日誌的,能夠指定 Logger 的級別以及自定義日誌的輸出。

7.Client 請求執行組件

Client 是負責 HTTP 請求執行的組件,Feign 將請求信息封裝好後會交由 Client 來執行。

默認狀況下,服務之間調用使用的HttpURLConnection,沒有使用鏈接池,每次使用都會建立HttpURLConnection鏈接,效率很是低。

爲了經過鏈接池提升效率,咱們可使用appache httpclient作爲鏈接池。固然了配置OkHttpClient鏈接池,也是相似的方法。

8.Retryer 重試組件

重試並非報錯之後的重試,而是負載均衡客戶端發現遠程請求實例不可到達後,去重試請求其餘實例。

Feign自己也具有重試能力,在早期的Spring Cloud中,Feign使用的是 feign.Retryer.Default#Default() ,重試5次。

但Feign整合了Ribbon,Ribbon也有重試的能力,此時,就可能會致使行爲的混亂。

Spring Cloud意識到了此問題,所以作了改進,將Feign的重試改成 feign.Retryer#NEVER_RETRY ,如需使用Feign的重試,只需使用Ribbon的重試配置便可。


9.RequestInterceptor 請求攔截器

咱們能夠經過實現RequestInterceptor接口的apply方法,在請求執行前設置一些擴展的參數信息或者是修改請求頭信息,由於feign在發送請求以前都會調用該接口的apply方法,因此咱們也能夠經過實現該接口來記錄請求發出去的時間點。

Fegin 的執行過程

 

與Fegin的纏綿悱惻

Fegin的原生API的使用





public interface GitHub { @RequestLine("GET /repos/{owner}/{repo}/contributors") List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repository); class Contributor { String login; int contributions; }}public class MyApp { public static void main(String[] args) { GitHub github = Feign.builder() .decoder(new GsonDecoder()) .target(GitHub.class, "https://api.github.com"); /* The owner and repository parameters will be used to expand the owner and repo expressions * defined in the RequestLine. * * the resulting uri will be https://api.github.com/repos/OpenFeign/feign/contributors */ github.contributors("OpenFeign", "feign"); }}

這段代碼是我從 OpenFeign 的 GitHub 主頁上示例代碼。

這是一個 GET 請求的示列,定義了一個 GitHub 的接口,接口中定義了一個查詢的方法和參數。在方法上有 @RequestLine 註解,定義了請求類型和請求的 URI,URI 中有對應的參數佔位符,返回值是集合,集合中是對應的返回結構對象。

咱們經過 Feign 的 builder 模式構建了 GitHub 接口對象後,就能夠直接經過 GiuHub 接口對象調用裏面的 contributors 方法,而後能夠獲得返回結果。Feign 的這種方式就跟 Dubbo 中的調用方式是同樣的,就像調用本地方法同樣。

使用原生的 Feign 來調用 API,只須要經過特定的註解來描述調用的 API 信息,這些信息的請求方式能夠是 GET 或者 POST 等,請求參數是什麼?請求的地址是什麼? 把這些信息定義好後就能夠直接使用這個定好了的接口來調用對應的遠程 API。

Fegin結合SpringCloud使用

1.首先建立一個OpenFeginClient模塊,pom.xml代碼以下:

 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>

2.在啓動類上添加 @EnableFeignClients 啓用 Feign





package com.javaer.study.openfeginclient;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.openfeign.EnableFeignClients;/** * @Author 公衆號【Java學習部落】 * * 關注公衆號獲取4000G精品視頻資源 * * 更有更多學習Java後端、中間件,大數據、微服務、分佈式、大數據等學習乾貨 **/@SpringBootApplication@EnableFeignClients@EnableEurekaClientpublic class OpenfeginclientApplication { public static void main(String[] args) { SpringApplication.run(OpenfeginclientApplication.class, args); }}

3.配置appliation.yml 註冊到Eureka Server。

server: port: 8888spring: application: name: spring-cloud-feign-openClienteureka: client: service-url: defaultZone: http://localhost:8761/eureka/

4.使用@FeignClient爲本應用聲明一個簡單的能調用的客戶端。爲了方便,咱們依然使用Github開放的api。



package com.javaer.study.openfeginclient;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;/** * 一個能夠調用的客戶端 * * @author topJavaer * 公衆號:【Java學習部落】 * @create 2020 11 10 * @Version 1.0.0 *///@FeignClient 便是指定客戶端信息註解,務必聲明在接口上面,url手動指定了客戶端的接口地址@FeignClient(name = "github-client", url = "https://api.github.com")public interface GitHubApiClient { @RequestMapping(value = "/search/repositories", method = RequestMethod.GET) String searchRepositories(@RequestParam("q") String queryStr);}

5.添加測試代碼






package com.javaer.study.openfeginclient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/** * 測試類 * * @author topJavaer * 公衆號:【Java學習部落】 * @create 2020 11 10 * @Version 1.0.0 */@RestControllerpublic class GitHubApiTest { @Resource private GitHubApiClient gitHubApiClient; @RequestMapping("/search/github/repository") public String searchGithubRepositoryByName(@RequestParam("name") String repositoryName) { return gitHubApiClient.searchRepositories(repositoryName); }}

6.最後咱們啓動以前再講述Eureka時編寫的Eureka Server,而後啓動該模塊。

訪問:http://localhost:8888/search/github/repository?name=spring-cloud-dubbo

獲得以下結果:

上述就是Spring Cloud 使用OpenFegin的基本流程,是否是很簡單,看一眼,操做一遍,立馬就會了,固然了,若是說想要深刻了解,僅僅這樣是遠遠不夠的,仍是須要你們本身繼續去專研,去深刻探究。

Fegin的核心註解@FeignClient詳解


package org.springframework.cloud.netflix.feign; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FeignClient {  @AliasFor("name") String value() default "";  @Deprecated String serviceId() default ""; @AliasFor("value")  String name() default "";  String qualifier() default "";  String url() default "";  boolean decode404() default false;  Class<?>[] configuration() default {};  Class<?> fallback() default void.class;  Class<?> fallbackFactory() default void.class;  String path() default "";  boolean primary() default true; }

name: 指定Feign Client的名稱,若是項目使用了 Ribbon,name屬性會做爲微服務的名稱,用於服務發現。

serviceId: 用serviceId作服務發現已經被廢棄,因此不推薦使用該配置。

value: 指定Feign Client的serviceId,若是項目使用了 Ribbon,將使用serviceId用於服務發現,但上面能夠看到serviceId作服務發現已經被廢棄,因此也不推薦使用該配置。

qualifier: 爲Feign Client 新增註解@Qualifier

url: 請求地址的絕對URL,或者解析的主機名

decode404: 調用該feign client發生了常見的404錯誤時,是否調用decoder進行解碼異常信息返回,不然拋出FeignException。

fallback: 定義容錯的處理類,當調用遠程接口失敗或超時時,會調用對應接口的容錯邏輯,fallback 指定的類必須實現@FeignClient標記的接口。實現的法方法即對應接口的容錯處理邏輯。

fallbackFactory: 工廠類,用於生成fallback 類示例,經過這個屬性咱們能夠實現每一個接口通用的容錯邏輯,減小重複的代碼。

path: 定義當前FeignClient的全部方法映射加統一前綴。

primary: 是否將此Feign代理標記爲一個Primary Bean,默認爲ture

Fegin的核心配置

Fegin的配置方式有兩種。

一種是Java 代碼配置,須要在主程序啓動入口用@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.java)來引用配置。

第二種是直接配置文件配置,在application.yml或者application.properties中配置。

咱們應該知道的是,若是經過Java代碼的方式配置 Feign,而後有經過屬性文件的方式配置Feign,屬性文件中的Frign的配置會覆蓋Java代碼的配置。

可是能夠配置 feign.client.default-to-properties=fasle來改變Feign配置生效的優先級。

本文主要講解一些平常經常使用的配置,經過配置文件。

Spring Cloud Feign 支持請求和響應進行GZIP壓縮來提升通訊效率。

      # 開啓GZIP壓縮配置      #請求GZIP壓縮 feign.compression.request.enable=true  #響應GIZP壓縮      feign.compression.response.enable=true               #壓縮支持的mime type feign.compression.request.mime-types=text/xml,application/xml.application/json  feign.compression.request.min-request-size=1024  #壓縮數據大小的最小值

Feign 爲每個FeignClient都提供了feign.logger實例,可在配置中或者java代碼中開啓日誌。




NONE 表示不輸出日誌。BASIC 表示只輸出請求方法的 URL 和響應的狀態碼以及執行的時間。HEADERS 將 BASIC 信息和請求頭信息輸出。FULL 會輸出所有完整的請求信息。

logging: level: com.javaer.study: debugfeign: client: config: # 要調用服務的名稱 java-master: loggerLevel: full

Fegin的超時配置

Ribbon 超時配置

當系統出現Read time out,說明是 Ribbon 超時了,須要在配置文件中進行控制處理

### Ribbon 配置ribbon: # 鏈接超時 ConnectTimeout: 2000 # 響應超時 ReadTimeout: 5000

Hystrix 超時配置

Fegin 高版本的 Hystrix 默認是關閉的。須要如下配置開啓:

### Feign 配置feign: # 開啓斷路器(熔斷器) hystrix: enabled: true

爲了不超時,咱們能夠根據業務狀況來配置本身的超時時間,此處配置熔斷時間爲:5000/毫秒。

注意:建議 Ribbon 的超時時間不要大於 Hystrix 的超時時間

### Hystrix 配置hystrix: # 這樣將會自動配置一個 Hystrix 併發策略插件的 hook,這個 hook 會將 SecurityContext 從主線程傳輸到 Hystrix 的命令。 # 由於 Hystrix 不容許註冊多個 Hystrix 策略,因此能夠聲明 HystrixConcurrencyStrategy # 爲一個 Spring bean 來實現擴展。Spring Cloud 會在 Spring 的上下文中查找你的實現,並將其包裝在本身的插件中。 shareSecurityContext: true command: default: circuitBreaker: # 當在配置時間窗口內達到此數量的失敗後,進行短路。默認20個 requestVolumeThreshold: 1 # 觸發短路的時間值,當該值設爲5000時,則當觸發 circuit break 後的5000毫秒內都會拒絕request # 也就是5000毫秒後纔會關閉circuit。默認5000 sleepWindowInMilliseconds: 15000 # 強制打開熔斷器,若是打開這個開關,那麼拒絕全部request,默認false forceOpen: false # 強制關閉熔斷器 若是這個開關打開,circuit將一直關閉且忽略,默認false forceClosed: false execution: isolation: thread: # 熔斷器超時時間,默認:1000/毫秒 timeoutInMilliseconds: 5000

Fegin的繼承特性

Spring Cloud Feign提供了繼承特性,所謂的繼承特性就是將一些公共操做提取到一個父接口中,從而繼承父接口中的操做,減小代碼的重複開發,節約開發成本。

一、優勢

    能夠將接口的定義從 Controller 中剝離,同時配合 Maven 私有倉庫就能夠輕易地實現接口定義的共享,不用再複製粘貼接口進行綁定,而是實如今構建期的接口綁定,從而有效減小服務客戶端的綁定配置。

二、缺點

    因爲接口在構建期間就創建起了依賴,那麼接口變更就會對項目構建形成影響,可能服務提供方修改了一個接口定義,那麼會直接致使客戶端工程的構建失敗。

    因此,若是開發團隊經過此方法來實現接口共享的話,建議在開發評審期間嚴格遵照面向對象的開閉原則,儘量地作好先後版本的兼容,防止牽一髮而動全身的後果,增長團隊沒必要要的維護工做量。

Fegin重試機制

在 Spring Cloud Feign 中默認實現了請求的重試機制,下面配置做用是:當訪問到故障請求的時候,它會再嘗試訪問一次當前實例(次數由 MaxAutoRetries 配置),若是不行,就換一個實例進行訪問,若是還不行,再換一次實例訪問(更換次數由 MaxAutoRetriesNextServer 配置),若是依然不行,返回失敗信息。

注意Ribbon 的超時與 Hystrix 的超時是兩個概念。爲了讓上述實現有效,咱們須要讓 Hystrix 的超時時間大於 Ribbon 的超時時間,不然 Hystrix 命令超時後,該命令直接熔斷,重試機制就沒有任何意義了。


#斷路器的超時時長鬚要大於Ribbon的超時時間,否則不會觸發重試hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000#請求鏈接超時時間fegin-service.ribbon.ConnectTimeout=500#請求處理的超時時間fegin-service.ribbon.ReadTimeout=1000#對全部請求都進行重試(是否全部操做都重試,若false則僅get請求重試)fegin-service.ribbon.OkToRetryOnAllOperations=true#對當前實例的重試次數fegin-service.ribbon.MaxAutoRetries=1#切換實例的重試次數fegin-service.ribbon.MaxAutoRetriesNextServer=2

總結

本文從面試常常問的幾個方面來介紹什麼是Fegin。

從Fegin的簡介和做用,Fegin九大核心組件,Fegin的執行過程,Fegin的核心註解@FeignClient的詳解,Fegin原生Api的使用,Fegin結合Spring Cloud使用,Fegin的經常使用配置詳解,Fegin的超時機制,繼承特性以及重試機制都是咱們在平常面試中常常碰見的。

也許本文講的不夠深刻,可是但願能給你們一個系統學習Fegin的框架,你們根據這個框架在不斷的深刻直到徹底掌握。

原創不易,若是你們喜歡,賞個分享點贊在看三連吧。和你們一塊兒成爲這世界上最優秀的人。

相關文章
相關標籤/搜索