問題發生的背景:
Feign在默認情況下使用的是JDK原生的URLConnection
發送HTTP請求,沒有連接池,但是對每個地址會保持一個長連接,即利用HTTP的persistence connection 。
我們可以用Apache的HTTP Client
替換Feign原始的http client, 從而獲取連接池、超時時間
等與性能息息相關的控制能力。Spring Cloud從Brixtion.SR5版本開始支持這種替換,
首先在項目中聲明Apache HTTP Client和feign-httpclient依賴:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpasyncclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>8.17.0</version> </dependency>
修改application.properties配置
feign.httpclient.enabled=true
FeignService Post接口
@FeignClient(name="eureka-client") public interface UserFeignService { @RequestMapping(value = "/user/update",method = RequestMethod.POST) String updateUser(@RequestBody User user); }
報錯如下:
java.lang.IllegalArgumentException: MIME type may not contain reserved characters
at org.apache.http.util.Args.check(Args.java:36) ~[httpcore-4.4.11.jar:4.4.11]
at org.apache.http.entity.ContentType.create(ContentType.java:227) ~[httpcore-4.4.11.jar:4.4.11]
at feign.httpclient.ApacheHttpClient.getContentType(ApacheHttpClient.java:159) ~[feign-httpclient-8.17.0.jar:8.17.0]
at feign.httpclient.ApacheHttpClient.toHttpUriRequest(ApacheHttpClient.java:140) ~[feign-httpclient-8.17.0.jar:8.17.0]
可以看出來是檢測Content-Type不合法報的異常,但在代碼中我們並沒有指定Content-Type,所以應該是使用了默認值。
feign.httpclient.ApacheHttpClient
private ContentType getContentType(Request request) { ContentType contentType = ContentType.DEFAULT_TEXT; Iterator var3 = request.headers().entrySet().iterator(); while(var3.hasNext()) { Entry<String, Collection<String>> entry = (Entry)var3.next(); if(((String)entry.getKey()).equalsIgnoreCase("Content-Type")) { Collection values = (Collection)entry.getValue(); if(values != null && !values.isEmpty()) { contentType = ContentType.create((String)((Collection)entry.getValue()).iterator().next(), request.charset()); break; } } }
return contentType; }
import org.springframework.http.MediaType;
@FeignClient(name="eureka-client") public interface UserFeignService { @RequestMapping(value = "/user/update",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE) String updateUser(@RequestBody User user); }
通過給@RequestMapping設置consumes參數