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

org.springframework.cloud
spring-cloud-starter-hystrix

```
第二步:在启动类上添加@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

io.github.openfeign.form
feign-form
3.0.3

io.github.openfeign.form
feign-form-spring
3.0.3

```
**编写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

io.github.openfeign.form
feign-form
3.2.2

io.github.openfeign.form
feign-form-spring
3.2.2

```
**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 post(Map queryParam);

class FormSupportConfig {
@Autowired
private ObjectFactory messageConverters;
// new一个form编码器,实现支持form表单提交
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
// 开启Feign的日志
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
}
```
**调用示例:**
```java
@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();
}
```
**日志:**
```code
...[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表单方式提交数据。

原文链接:http://www.itmuch.com/spring-cloud-sum/feign-form-params/

### Feign GET请求如何构造多参数
假设需请求的URL包含多个参数,例如http://microservice-provider-user/get?id=1&username=张三 ,该如何使用Feign构造呢?
我们知道,Spring Cloud为Feign添加了Spring MVC的注解支持,那么我们不妨按照Spring MVC的写法尝试一下:
```java
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get0(User user);
}
```
然而,这种写法并不正确,控制台会输出类似如下的异常。
```code
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方法,Feign依然会使用POST方法发送请求。于是导致了异常。正确写法如下

**方法一[推荐]**
**注意:使用该方法无法使用Fegin的继承模式**
```java
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@GetMapping("/get")
public User get0(@SpringQueryMap User user);
}
```
**方法二[推荐]**
```java
@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有几个参数,Feign接口中的方法就有几个参数。使用@RequestParam注解指定请求的参数是什么。

**方法三[不推荐]**
多参数的URL也可使用Map来构建。当目标URL参数非常多的时候,可使用这种方式简化Feign接口的编写。
```java
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get2(@RequestParam Map map);
}
```
在调用时,可使用类似以下的代码。
```java
public User get(String username, String password) {
HashMap map = Maps.newHashMap();
map.put("id", "1");
map.put("username", "张三");
return this.userFeignClient.get2(map);
}
```
**注意:**这种方式不建议使用。主要是因为可读性不好,而且如果参数为空的时候会有一些问题,例如`map.put("username", null);` 会导致服务调用方(消费者服务)接收到的username是"" ,而不是null。

原文链接:http://www.itmuch.com/spring-cloud-sum/feign-multiple-params-2/

### 切换为 Okhttp3 提升 QPS 性能优化
**加依赖引入okhttp3**
```pom

io.github.openfeign
feign-okhttp
${version}

```
**写配置**
```yml
feign:
# feign启用hystrix,才能熔断、降级
# hystrix:
# enabled: true
# 启用 okhttp 关闭默认 httpclient
httpclient:
enabled: false #关闭httpclient
# 配置连接池
max-connections: 200 #feign的最大连接数
max-connections-per-route: 50 #fegin单个路径的最大连接数
okhttp:
enabled: true
# 请求与响应的压缩以提高通信效率
compression:
request:
enabled: true
min-request-size: 2048
mime-types: text/xml,application/xml,application/json
response:
enabled: true
```
**参数配置**
```java
/**
* 配置 okhttp 与连接池
* ConnectionPool 默认创建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();
}
}
```
原文链接:https://mp.weixin.qq.com/s/PAjXS9d6Sxa04pw1Lw2HXQ

[赵小胖个人博客](https://zc.happyloves.cn:4443/wordpress/)

Spring Cloud Feign 总结问题,注意点,性能调优,切换okhttp3的更多相关文章

  1. 笔记:Spring Cloud Feign 其他配置

    请求压缩 Spring Cloud Feign 支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗,我们只需要通过下面二个参数设置,就能开启请求与响应的压缩功能,yml配置格式如下: fei ...

  2. 使用Spring Cloud Feign

    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务 在spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就 ...

  3. Spring cloud Feign 深度学习与应用

    简介 Spring Cloud Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单.Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解 ...

  4. spring cloud微服务快速教程之(十四)spring cloud feign使用okhttp3--以及feign调用参数丢失的说明

    0-前言 spring cloud feign 默认使用httpclient,需要okhttp3的可以进行切换 当然,其实两者性能目前差别不大,差别较大的是很早之前的版本,所以,喜欢哪个自己选择: 1 ...

  5. 笔记:Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  6. 笔记:Spring Cloud Feign Hystrix 配置

    在 Spring Cloud Feign 中,除了引入了用户客户端负载均衡的 Spring Cloud Ribbon 之外,还引入了服务保护与容错的工具 Hystrix,默认情况下,Spring Cl ...

  7. 笔记:Spring Cloud Feign 声明式服务调用

    在实际开发中,对于服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以我们通常会针对各个微服务自行封装一些客户端类来包装这些依赖服务的调用,Spring Cloud Feign 在此基础上做了进 ...

  8. 第六章:声明式服务调用:Spring Cloud Feign

    Spring Cloud Feign 是基于 Netflix Feign 实现的,整合了 Spring Cloud Ribbon 和 Spring Cloud Hystrix,除了提供这两者的强大功能 ...

  9. Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  10. Spring Cloud feign

    Spring Cloud feign使用 前言 环境准备 应用模块 应用程序 应用启动 feign特性 综上 1. 前言 我们在前一篇文章中讲了一些我使用过的一些http的框架 服务间通信之Http框 ...

随机推荐

  1. JavaScript简单的弹幕

    弹幕 首先是弹幕的位置,是要从最右滑到最左,为了防止随机高度弹幕会覆盖的问题,设置了通道. 每一个通道是从左到右的一条,高度固定,这样不同通道的弹幕不会相互覆盖. 弹幕滑动就是简单设置CSS属性  t ...

  2. python实现煲机脚本

    生日的时候女票送了一副新耳机,还挺帅气. 装逼界的人都知道,新耳机是有"煲"这个步骤的 至于有没有效果?怎么煲?煲多久?这些问题都是耳机界常年争执的问题,各路高手分成各种门派常年杀 ...

  3. 【Offer】[58-1] 【翻转单词顺序】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母样处理.例如输入字符串"I am ...

  4. text2pcap: 将hex转储文本转换为Wireshark可打开的pcap文件

    简介 Text2pcap是一个读取ASCII hex转储的程序,它将描述的数据写入pcap或pcapng文件.text2pcap可以读取包含多个数据包的hexdumps,并构建多个数据包的捕获文件.t ...

  5. [整理] jQuery插件开发

    1.类级别的插件开发 类级别的插件开发,可似为给jQuery类添加方法,调用方式:$.你的方法(),如:$.ajax() 函数. 1.1.给jQuery类添加方法 $.alertMsg = funct ...

  6. 搭建自己的技术博客系列(五)hexo博客接入busuanzi插件,展示访问量和网站运行时间

    busuanzi计数脚本 busuanzi官方指引 一.安装脚本(必选) 要使用不蒜子必须在页面中引入busuanzi.js,目前最新版如下. 不蒜子可以给任何类型的个人站点使用,如果你是用的hexo ...

  7. SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询

    背景&痛点 通过ES进行查询,如果需要新增查询条件,则每次都需要进行硬编码,然后实现对应的查询功能.这样不仅开发工作量大,而且如果有多个不同的索引对象需要进行同样的查询,则需要开发多次,代码复 ...

  8. 记一次oracle新建用户及分配指定表权限的操作记录

    1.登录 2.创建用户create user new用户名 identified by new用户名创建new用户名用户,密码设置为new用户名. 3.授权new用户名用户的连接.资源权限.grant ...

  9. (1)定义闭合图形抽象类ClosedFigure定义属性:1.形状;2.定义构造方法,给形状赋值;3.定义两个抽象方法:计算面积和计算周长;4.定义一个显示方法:显示图像形状,周长,面积;

    题目显示不全,完整题目描述: (1)定义闭合图形抽象类ClosedFigure定义属性:1.形状:2.定义构造方法,给形状赋值:3.定义两个抽象方法:计算面积和计算周长:4.定义一个显示方法:显示图像 ...

  10. 亮剑.NET第二章

    第二章主要讲解C#中各种让人模糊不清的概念,用法,类型等等. 1.Equals()与==区别 当比较两个值类型时,二者基本一致,当比较引用类型时,==比较的是引用类型的地址是否一致,即两个引用是否指向 ...