Feign是一种声明式,模板化的客户端,通过@Feignclient注解申明一个feign客户端
- 采用基于接口的注解
- Feign整合了ribbon,具有负载均衡的能力
- 整合了Hystrix,具有熔断的能力
- name属性: 指定调用该接口方法注册在eureka上的服务名,从而得到服务的地址,支持占位符,通过配置中心修改,有利于解耦合
- configuration属性: 指定feign的配置类信息,默认组件
- Decoder/Encoder
- Logger: Slf4jLogger
- Contract: SpringMvcContract
- Feign.Builder: HystrixFeign.Builder
- Client: LoadBalancerFeignClient(Ribbon激活的话)
Feign的调用编码器使用feignEncoder,它为自动识别@RequestParam注解后的参数并解码成字符串拼接在URL后面,默认是采用spring的实现SpringEncoder,该实现使用Spring的HttpMessageConverter进行请求体写入,详细源码查看FeignClientConfiguration类
当有需要表单或文件上传写入时,其编码器也是将参数拼接在了URL后面,这肯定是不行的,springcloud也做了这方面实现,添加如下依赖即可
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>2.1.0</version>
</dependency>
Feign的响应状态码处理采用ErrorDecoder,该错误处理器会返回异常信息,可以在feign调用的地方捕捉到异常
@FeignClient注解被@Target({ElementType.TYPE})修饰,表明该注解的作用目标在接口
@Retention(RetentionPolicy.RUNTIME) 注解会在.class字节码文件中存在,且在运行中通过反射获取到
@Documented 表示该注解被包含在javadoc文件中
Feign默认使用HttpURLConnection,若要使用okHttpclient,在pom.xml文件加上okHttpclient的classpath就行了,它由FeignRibbonClientAutoConfiguration类自动装配,通过@ConditionalOnClass(ApacheHttpClient.class)注解
Feign是如何实现负载均衡的
通过配置feign的客户端依赖,最终向容器中注入的是LoadBalancerFeignClient
总结:
- 首先通过@EnableFeignclients开启Feignclient
- 根据feign的规则实现接口,并添加@Feignclient注解
- 程序启动会自动包扫描被@Feignclient注解修饰的类,并添加到IOC容器中
- 当接口方法被调用时,根据JDK动态代理,生成具体的RestTemplate
- requestTemplate在生成request
- request交给client处理,具体使用根据导入的maven依赖,可以是HttpURLClient,也可以是OkHttpClient
- 最终client被封装进LoadBalancerFeignClient类,该类结合ribbion实现了负载均衡