Feign常見問題總結
FeignClient接口如使用@PathVariable ,必須指定value屬性
//在一些早期版本中, @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的注意點與坑
@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共享,無法實現(xiàn)細粒度配置!
* 個人建議:像我一樣,不加@Configuration注解
*
* @author zhouli
*/
class UserFeignConfig {
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
- 配置類上也可添加@Configuraiton 注解,聲明這是一個配置類;但此時千萬別將該放置在主應用程序上下文@ComponentScan 所掃描的包中,否則,該配置將會被所有Feign Client共享(相當于變成了通用配置,其實本質還是Spring父子上下文掃描包重疊導致的問題),無法實現(xiàn)細粒度配置!
- 個人建議:像我一樣,不加@Configuration注解,省得進坑。
- 最佳實踐:盡量用配置屬性自定義Feign的配置!??!
@FeignClient 注解屬性
//@FeignClient(name = "microservice-provider-user")
//在早期的Spring Cloud版本中,無需提供name屬性,從Brixton版開始,@FeignClient必須提供name屬性,否則應用將無法正常啟動!
//另外,name、url等屬性支持占位符。例如:
@FeignClient(name = "${feign.name}", url = "${feign.url}")
類級別的@RequestMapping會被Spring MVC加載
@RequestMapping("/users")
@FeignClient(name = "microservice-user")
public class TestFeignClient {
// ...
}
類上的@RequestMapping 注解也會被Spring MVC加載。該問題現(xiàn)已經(jīng)被解決,早期的版本有兩種解決方案:
方案1:不在類上加@RequestMapping 注解;
方案2:添加如下代碼:
@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)模式
如需產(chǎn)生Hystrix Stream監(jiān)控信息,需要做一些額外操作
Feign本身已經(jīng)整合了Hystrix,可直接使用@FeignClient(value = "microservice-provider-user", fallback = XXX.class) 來指定fallback類,fallback類繼承@FeignClient所標注的接口即可。
但是假設如需使用Hystrix Stream進行監(jiān)控,默認情況下,訪問http://IP:PORT/actuator/hystrix.stream 是會返回404,這是因為Feign雖然整合了Hystrix,但并沒有整合Hystrix的監(jiān)控。如何添加監(jiān)控支持呢?需要以下幾步:
第一步:添加依賴,示例:
org.springframework.cloudspring-cloud-starter-hystrix
第二步:在啟動類上添加@EnableCircuitBreaker 注解,示例:
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieFeignHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(MovieFeignHystrixApplication.class, args);
}
}
第三步:在application.yml中添加如下內容,暴露hystrix.stream端點:
management:
endpoints:
web:
exposure:
include: 'hystrix.stream'
這樣,訪問任意Feign Client接口的API后,再訪問http://IP:PORT/actuator/hystrix.stream ,就會展示一大堆Hystrix監(jiān)控數(shù)據(jù)了。
原文鏈接:http://www.itmuch.com/spring-...
Feign 上傳文件
加依賴
io.github.openfeign.formfeign-form3.0.3io.github.openfeign.formfeign-form-spring3.0.3
編寫Feign Client
@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就能夠上傳啦。
注意點
//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-...
Feign實現(xiàn)Form表單提交
添加依賴:
io.github.openfeign.formfeign-form3.2.2io.github.openfeign.formfeign-form-spring3.2.2
Feign Client示例:
@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 post(Map queryParam);
class FormSupportConfig {
@Autowired
private ObjectFactory messageConverters;
// new一個form編碼器,實現(xiàn)支持form表單提交
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
// 開啟Feign的日志
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
},>
調用示例:
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
HashMap param = Maps.newHashMap();
param.put("username","zhangsan");
param.put("password","pwd");
this.testFeignClient.post(param);
return new User();
},>
日志:
...[TestFeignClient#post] ---> POST http://www.baidu.com/test HTTP/1.1
...[TestFeignClient#post] Accept: application/json;charset=UTF-8
...[TestFeignClient#post] Content-Type: application/x-www-form-urlencoded; charset=UTF-8
...[TestFeignClient#post] Content-Length: 30
...[TestFeignClient#post]
...[TestFeignClient#post] password=pwd&username=zhangsan
...[TestFeignClient#post] ---> END HTTP (30-byte body)
由日志可知,此時Feign已能使用Form表單方式提交數(shù)據(jù)。
原文鏈接:http://www.itmuch.com/spring-...
Feign GET請求如何構造多參數(shù)
假設需請求的URL包含多個參數(shù),例如http://microservice-provider-... ,該如何使用Feign構造呢?
我們知道,Spring Cloud為Feign添加了Spring MVC的注解支持,那么我們不妨按照Spring MVC的寫法嘗試一下:
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get0(User user);
}
然而,這種寫法并不正確,控制臺會輸出類似如下的異常。
feign.FeignException: status 405 reading UserFeignClient#get0(User); content:
{"timestamp":1482676142940,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/get"}
由異??芍?,盡管我們指定了GET方法,F(xiàn)eign依然會使用POST方法發(fā)送請求。于是導致了異常。正確寫法如下
方法一[推薦]
注意:使用該方法無法使用Fegin的繼承模式
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@GetMapping("/get")
public User get0(@SpringQueryMap User user);
}
方法二[推薦]
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get1(@RequestParam("id") Long id, @RequestParam("username") String username);
}
這是最為直觀的方式,URL有幾個參數(shù),F(xiàn)eign接口中的方法就有幾個參數(shù)。使用@RequestParam注解指定請求的參數(shù)是什么。
方法三[不推薦]
多參數(shù)的URL也可使用Map來構建。當目標URL參數(shù)非常多的時候,可使用這種方式簡化Feign接口的編寫。
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get2(@RequestParam Map map);
},>
在調用時,可使用類似以下的代碼。
public User get(String username, String password) {
HashMap map = Maps.newHashMap();
map.put("id", "1");
map.put("username", "張三");
return this.userFeignClient.get2(map);
},>
注意:這種方式不建議使用。主要是因為可讀性不好,而且如果參數(shù)為空的時候會有一些問題,例如map.put("username", null); 會導致服務調用方(消費者服務)接收到的username是"" ,而不是null。
原文鏈接:http://www.itmuch.com/spring-...
切換為 Okhttp3 提升 QPS 性能優(yōu)化
加依賴引入okhttp3
io.github.openfeignfeign-okhttp${version}
寫配置
feign:
# feign啟用hystrix,才能熔斷、降級
# hystrix:
# enabled: true
# 啟用 okhttp 關閉默認 httpclient
httpclient:
enabled: false #關閉httpclient
# 配置連接池
max-connections: 200 #feign的最大連接數(shù)
max-connections-per-route: 50 #fegin單個路徑的最大連接數(shù)
okhttp:
enabled: true
# 請求與響應的壓縮以提高通信效率
compression:
request:
enabled: true
min-request-size: 2048
mime-types: text/xml,application/xml,application/json
response:
enabled: true
參數(shù)配置
/**
* 配置 okhttp 與連接池
* ConnectionPool 默認創(chuàng)建5個線程,保持5分鐘長連接
*/
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class) //SpringBoot自動配置
public class OkHttpConfig {
// 默認老外留給你彩蛋中文亂碼,加上它就 OK
@Bean
public Encoder encoder() {
return new FormEncoder();
}
@Bean
public okhttp3.OkHttpClient okHttpClient() {
return new okhttp3.OkHttpClient.Builder()
//設置連接超時
.connectTimeout(10, TimeUnit.SECONDS)
//設置讀超時
.readTimeout(10, TimeUnit.SECONDS)
//設置寫超時
.writeTimeout(10, TimeUnit.SECONDS)
//是否自動重連
.retryOnConnectionFailure(true)
.connectionPool(new ConnectionPool(10, 5L, TimeUnit.MINUTES))
.build();
}
}
-
Linux
+關注
關注
88文章
11778瀏覽量
219176 -
JAVA
+關注
關注
20文章
3002瀏覽量
116564 -
數(shù)據(jù)庫
+關注
關注
7文章
4033瀏覽量
68416 -
python
+關注
關注
58文章
4878瀏覽量
90139
發(fā)布評論請先 登錄
HarmonyOSAI編程智慧調優(yōu)
EDAS再升級!全面支持Spring Cloud應用
基于全HDD aarch64服務器的Ceph性能調優(yōu)實踐總結
架構分析高效HTTP客戶端OkHttp有什么優(yōu)勢
Spring Cloud Feign性能優(yōu)化
基于SharedPreferences的OkHttp3的持久CookieJar實現(xiàn)
Spring Cloud Tencent發(fā)布最新匹配版本!
Spring Cloud 2022.0.0正式發(fā)布
dubbo和spring cloud區(qū)別
鴻蒙OS封裝【axios 網(wǎng)絡請求】(類似Android的Okhttp3)
Spring Cloud Gateway網(wǎng)關框架
Spring Cloud Feign總結問題,注意點,性能調優(yōu),切換okhttp3
評論