Spring Cloud Feign 總結問題,注意點,效能調優,切換okhttp3
阿新 • • 發佈:2019-10-14
### Feign常見問題總結
**FeignClient介面如使用`@PathVariable` ,必須指定value屬性**
```java
//在一些早期版本中, @PathVariable("id") 中的 "id" ,也就是value屬性,必須指定,不能省略。
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
...
}
```
**Java程式碼自定義Feign Client的注意點與坑**
```java
@FeignClient(name = "microservice-provider-user", configuration = UserFeignConfig.class)
public interface UserFeignClient {
@GetMapping("/users/{id}")
User findById(@PathVariable("id") Long id);
}
/**
* 該Feign Client的配置類,注意:
* 1. 該類可以獨立出去;
* 2. 該類上也可新增@Configuration宣告是一個配置類;
* 配置類上也可新增@Configuration註解,宣告這是一個配置類;
* 但此時千萬別將該放置在主應用程式上下文@ComponentScan所掃描的包中,
* 否則,該配置將會被所有Feign Client共享,無法實現細粒度配置!
* 個人建議:像我一樣,不加@Configuration註解
*
* @author zhouli
*/
class UserFeignConfig {
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
```
- 配置類上也可新增@Configuraiton 註解,宣告這是一個配置類;但此時千萬別將該放置在主應用程式上下文@ComponentScan 所掃描的包中,否則,該配置將會被所有Feign Client共享(相當於變成了通用配置,其實本質還是Spring父子上下文掃描包重疊導致的問題),無法實現細粒度配置!
- **個人建議:**像我一樣,不加@Configuration註解,省得進坑。
- **最佳實踐:**儘量用配置屬性自定義Feign的配置!!!
**@FeignClient 註解屬性**
```java
//@FeignClient(name = "microservice-provider-user")
//在早期的Spring Cloud版本中,無需提供name屬性,從Brixton版開始,@FeignClient必須提供name屬性,否則應用將無法正常啟動!
//另外,name、url等屬性支援佔位符。例如:
@FeignClient(name = "${feign.name}", url = "${feign.url}")
```
**類級別的@RequestMapping會被Spring MVC載入**
```java
@RequestMapping("/users")
@FeignClient(name = "microservice-user")
public class TestFeignClient {
// ...
}
```
類上的`@RequestMapping` 註解也會被Spring MVC載入。該問題現已經被解決,早期的版本有兩種解決方案:
**方案1:**不在類上加@RequestMapping 註解;
**方案2:**新增如下程式碼:
```java
@Configuration
@ConditionalOnClass({ Feign.class })
public class FeignMappingDefaultConfiguration {
@Bean
public WebMvcRegistrations feignWebRegistrations() {
return new WebMvcRegistrationsAdapter() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new FeignFilterRequestMappingHandlerMapping();
}
};
}
private static class FeignFilterRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected boolean isHandler(Class beanType) {
return super.isHandler(beanType) && !beanType.isInterface();
}
}
}
```
**首次請求失敗**
Ribbon的飢餓載入(eager-load)模式
**如需產生Hystrix Stream監控資訊,需要做一些額外操作**
Feign本身已經整合了Hystrix,可直接使用`@FeignClient(value = "microservice-provider-user", fallback = XXX.class)` 來指定fallback類,fallback類繼承`@FeignClient`所標註的介面即可。
但是假設如需使用Hystrix Stream進行監控,預設情況下,訪問http://IP:PORT/actuator/hystrix.stream 是會返回404,這是因為Feign雖然整合了Hystrix,但並沒有整合Hystrix的監控。如何新增監控支援呢?需要以下幾步:
第一步:新增依賴,示例:
```pom
```
第二步:在啟動類上新增@EnableCircuitBreaker 註解,示例:
```java
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieFeignHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(MovieFeignHystrixApplication.class, args);
}
}
```
第三步:在application.yml中新增如下內容,暴露hystrix.stream端點:
```yml
management:
endpoints:
web:
exposure:
include: 'hystrix.stream'
```
這樣,訪問任意Feign Client介面的API後,再訪問http://IP:PORT/actuator/hystrix.stream ,就會展示一大堆Hystrix監控資料了。
原文連結:http://www.itmuch.com/spring-cloud-sum/feign-problems/
#### Feign 上傳檔案
**加依賴**
```pom
```
**編寫Feign Client**
```java
@FeignClient(name = "ms-content-sample", configuration = UploadFeignClient.MultipartSupportConfig.class)
public interface UploadFeignClient {
@RequestMapping(value = "/upload", method = RequestMethod.POST,
produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
String handleFileUpload(@RequestPart(value = "file") MultipartFile file);
class MultipartSupportConfig {
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder();
}
}
}
```
如程式碼所示,在這個Feign Client中,我們引用了配置類`MultipartSupportConfig` ,在`MultipartSupportConfig` 中,我們例項化了`SpringFormEncoder` 。這樣這個Feign Client就能夠上傳啦。
**注意點**
-
```java
//RequestMapping註解中的produeces 、consumes 不能少;
@RequestMapping(value = "/upload", method = RequestMethod.POST,
produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
```
- 介面定義中的註解`@RequestPart(value = "file")` 不能寫成`@RequestParam(value = "file")` 。
- 最好將Hystrix的超時時間設長一點,例如5秒,否則可能檔案還沒上傳完,Hystrix就超時了,從而導致客戶端側的報錯。
原文連結:http://www.itmuch.com/spring-cloud-sum/spring-cloud-feign-upload/
#### Feign實現Form表單提交
**新增依賴:**
```pom
```
**Feign Client示例:**
```java
@FeignClient(name = "xxx", url = "http://www.itmuch.com/", configuration = TestFeignClient.FormSupportConfig.class)
public interface TestFeignClient {
@PostMapping(value = "/test",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
)
void