1. 程式人生 > >Spring Cloud Feign 總結問題,注意點,效能調優,切換okhttp3

Spring Cloud Feign 總結問題,注意點,效能調優,切換okhttp3

### 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