OpenFeign 是一個基於 Netflix Feign 實現的 Java HTTP 客戶端開發工具,它簡化了使用 Ribbon 時自定義 http 請求的過程。OpenFeign 通過註解的方式定義和實現了 RESTful API 的接口,使得調用遠程 HTTP 服務更加簡單和易用。本文將從多個方面對 OpenFeign 進行詳細闡述。
一、OpenFeign原理
OpenFeign 在實現上是基於 Feign 的,其底層依賴 Ribbon。Ribbon 是一個負載均衡客戶端,它可以自動化地完成客戶端的負載均衡。OpenFeign 通過註解的方式定義和實現了 RESTful API 接口,並集成了 Ribbon,將 RESTful API 接口轉化為 HTTP 請求並發送,最後將返回的數據轉化為接口的返回值。
OpenFeign 的主要原理如下:
1. 用戶通過接口定義和註解的方式定義一個 RESTful 接口
2. OpenFeign 在運行時會自動生成一個接口的代理類
3. 每當用戶通過代理類調用接口時,OpenFeign 實際上會通過 Ribbon 向多個服務實例發送 HTTP 請求
4. Ribbon 會根據負載均衡算法選出一台可用的服務,並將請求發送給該服務
5. 接收到請求的服務會將請求轉化成數據
6. 返回的數據再會被 OpenFeign 自動轉換成接口期望的返回值類型,並返回給調用方
二、OpenFeign使用什麼網絡協議
OpenFeign 的底層網絡協議是 HTTP 協議。 在幫助開發者快速開發微服務架構中,它可以與 Eureka、Zookeeper 等註冊中心進行集成使用,並支持多種 HTTP 註解及默認集成了 Ribbon 。
三、OpenFeign使用
下面分別對 OpenFeign 的註解和配置進行介紹。
1. 註解
@FeignClient 註解
該註解用於聲明一個 Feign 客戶端,並定義服務名稱和路徑前綴。其中:
– value屬性為遠程服務名,即 Eureka 註冊中心中的服務名,如果不指定,則使用 HTTP 地址;
– path屬性為微服務的 context-path,可理解為修改調用的 URL 前綴,會被自動添加到所有請求地址前面。
例如:
“`java
@FeignClient(value = “hello-service”, path = “/api”)
public interface Client {
@GetMapping(“/hello”)
String hello();
}
“`
@RequestMaping 註解
該註解用於聲明一個 HTTP 請求,包括 `GET` 、 `POST` 、 `PUT` 、 `DELETE` 、 `HEAD` 、 `OPTIONS` 、 `PATCH` 等請求方式,並且可以指定請求路徑的 URL、請求參數、請求體等信息。
例如:
“`java
@FeignClient(value = “hello-service”, path = “/api”)
public interface Client {
@RequestMapping(value = “/hello”, method = RequestMethod.GET)
String hello();
@RequestMapping(value = “/greeting”, method = RequestMethod.POST)
String greeting(@RequestBody User user);
}
“`
2. 配置
OpenFeign 也支持一些相關的配置,如請求超時時間、日誌級別等。
以下是服務提供方主體類中的 OpenFeign 配置:
“`java
@EnableFeignClients
@RibbonClient(name = “hello-service”)
@SpringBootApplication
public class App {
@Bean
public RequestInterceptor requestInterceptor(){
return new FeignRequestInterceptor();
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
“`
其中,使用 `@RibbonClient` 聲明 Ribbon 客戶端,name指定微服務名稱;使用 `@EnableFeignClients` 啟用 Feign 客戶端;通過定義一個 RequestInterceptor 來實現請求響應攔截。
四、OpenFeign源碼
OpenFeign 的源碼託管在 GitHub 上,倉庫的地址為:https://github.com/OpenFeign/feign。
五、OpenFeign面試題
1. OpenFeign 的原理是什麼?
2. OpenFeign 使用什麼網絡協議?
3. OpenFeign 如何定義 HTTP 請求?
4. 如何使用 Ribbon 和 Feign 集成負載均衡?
5. 如何設置 OpenFeign 的請求超時時間和日誌級別?
六、OpenFeign和Feign的區別
Feign 是一個 RESTful 的 HTTP 客戶端工具,是 Netflix 開源的,主要用於快速開發 RESTful 聲明式 Web 服務。而 OpenFeign 是對 Feign 進行了擴展和增強,主要在以下方面有所優化:
1. 在 Feign 的基礎上增加了 Ribbon 的支持
2. 增加了對 Hystrix 的支持,可實現服務的負載均衡和斷路器模式
3. 加強了對 Spring Boot 的支持
七、OpenFeign和Feign
在很多方面,OpenFeign 應該與 Feign 等效,在使用上差不多。 OpenFeign 實現了 Feign 的功能,再加上了對 Eureka、Ribbon 和 Hystrix 的支持,使得它更加適用於微服務架構。
八、調用直接報數據轉換失敗
在使用 OpenFeign 進行微服務互調時,可能會遇到以下錯誤:
“`
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
“`
這是因為默認情況下,OpenFeign 會使用 Jackson 將 JSON 數據轉換為接口的返回值類型,但是接口的返回值類型不匹配 JSON 數據的格式。
為了解決這個問題,需要自定義一個對象承接返回的數據,如下:
“`java
public class Result {
private Integer code;
private String message;
private T data;
//… getter and setter
}
“`
然後,在接口的返回值類型中使用該對象代替,並在 Feign 的配置中增加對返回數據的轉化,如下:
“`java
@EnableFeignClients(basePackages = “com.example.feignclient”)
@SpringBootApplication
public class Application {
@Bean
public Decoder decoder() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return new ResponseEntityDecoder(new SpringDecoder(new ObjectMapper()));
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
“`
九、OpenFeign底層原理
OpenFeign 的底層原理可以概括如下:
1. 使用 Java 動態代理機制,將接口的方法生成一個代理類
2. 通過 Spring Cloud Discovery Client 實現的 Ribbon 進行服務發現並進行負載均衡
3. 將請求拼接成 HTTP 請求發送出去,未針對請求結果進行處理
4. 得到結果後通過 Spring Cloud 的消息轉換器進行解碼並將數據傳遞給 Consumer 端。
通過這個實現,OpenFeign 將服務間的調用、異常處理、超時等都做得很好,方便了開發者進行服務調用和服務治理。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/237631.html