Feign的工作原理?
- 在开发微服务应用时,我们会在主程序入口添加@EnableFeignClients注解开启对FeignClient扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClients注解。
- 当程序启动时,会进行包扫描,扫描所有@FeignClients的注解的类,并将这些信息注人Spring IOC容器中。当定义的Feign接口中的方法被调用时,通过JDK的代理的方式,来生成具体的RequestTemplate。当生成代理时,Feign 会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,如请求参数名、请求方法等信息都是在这个过程中确定的。
- 然后由RequestTemplate 生成Request,然后把Request交给Client去处理,这里指的Client可以是JDK原生的URLConnection、Apache的 Http Client,也可以是Okhttp。最后Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发起服务之间的调用。
FeignClient注解被@Target .(ElementType.TYPE)修饰,表示FeignClient注解的作用目标在接口上。当打开org.springframework.cloud.openfeign.FeignClient这个注解定义类的时候,可以看到FeignClient注解对应的属性。
FeignClient注解的常用属性归纳如下:
- name :指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现。
- url: url一般用于调试,可以手动指定@FeignClient调用的地址。
- decode404 :当发生404错误时,如果该字段为true,会调用decoder进行解码,否则抛出FeignException。
- configuration: Feign配置类,可以自定义Feign的 Encoder、Decoder、LogLevel、Contract。fallback :定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口。
- fallbackFactory : 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码。
- path:定义当前FeignClient的统一前缀。
Feign开户GZIP压缩功能
Spring Cloud Feign支持对请求和响应进行GZIP压缩,以提高通信效率,这里介绍两种不同的配置方式,即 application.yml和 application.properties 的配置方式。具体的案例代码如ch4-1/ch4-1-gzip所示,案例代码比较简单可以直接运行学习,下面将对Feign开启GZIP压缩的配置进行说明。
application.yml
server:
port: 8011
spring:
application:
name: ch4-1-gzip
logging:
level:
cn.springcloud.book.feign.service.HelloFeignService: debug
feign:
compression:
request:
enabled: true
mime-types: text/xml,application/xml,application/json # 配置压缩支持的MIME TYPE
min-request-size: 2048 # 配置压缩数据大小的下限
response:
enabled: true # 配置响应GZIP压缩
等价与application.properties
#配置请求GzIP压缩
feign .compression. request.enabled=true#配置响应GzIP压缩
feign .compression. response.enabled=true#配置压缩支持的MIMETYPE
feign.compression.request.mime-types=text/xml, application/xml, application/json#配置压缩数据大小的下限
feign .compression.request.min-request-size=2048
由于开启GZIP压缩之后,Feign之间的调用通过二进制协议进行传输,返回值需要修改为ResponseEntity才可以正常显示,否则会导致服务之间的调用结果乱码,对应的Feign的Client处理如代码清单
@FeignClient(name = "github-client", url = "https://api.github.com", configuration = HelloFeignServiceConfig.class)
public interface HelloFeignService {
/**
* content: {"message":"Validation Failed","errors":[{"resource":"Search","field":"q","code":"missing"}],
* "documentation_url":"https://developer.github.com/v3/search"}
* @param queryStr
* @return
*/
@RequestMapping(value = "/search/repositories", method = RequestMethod.GET)
ResponseEntity searchRepo(@RequestParam("q") String queryStr);
}
Controller层也要修改
@RestController
public class HelloFeignController {
@Autowired
private HelloFeignService helloFeignService;
// 服务消费者对位提供的服务
@GetMapping(value = "/search/github")
public ResponseEntity searchGithubRepoByStr(@RequestParam("str") String queryStr) {
return helloFeignService.searchRepo(queryStr);
}
}
Feign支持属性文件配置
1.对单个指定特定名称的Feign进行配置
@FeignClient的配置信息可以通过application.properties或application.yml来配置,application.yml示例配置信息如下:
feign :
client :
config :
feignName: #需要配置的FeignName
connectTimeout: 500o#连接超时时间readTimeout: 500o
#读超时时间设置
loggerLevel: full
#配置Feign的日志级别
errorDecoder: com.example.simpleErrorDecoder #Feign的错误解码器retryer : com.example.simpleRetryer #配置重试
requestInterceptors:#配置拦截器
- com. example.FooRequestInterceptor- com. example.BarRequestInterceptordecode404 : false
encoder: com.example.simpleEncoder#Feign的编码器decoder: com.example.simpleDecoder #Feign的解码器
contract: com.example.simplecontract #Feign的Contract配置
⒉.作用于所有Feign的配置方式
@EnableFeignClients注解上有个defaultConfiguration属性,我们可以将默认配置写成一个类,比如这个配置类叫DefaultFeignConfiguration.java,在主程序的启动人口用defaultConfi-guration来引用配置,示例配置如下所示:
springBootApplication
EnableFeignclients(defaultConfiguration =DefaultFeignconfiguration.class )public class ConsumerApplication {
public static void main (string[] args) {
SpringApplication.run (ConsumerApplication.class,args) ;
}
feign :
client :
config:
default:
connectTimeout: 500
oreadTimeout: 500
loggerLevel: basic
注意,如果通过Java代码的方式配置过Feign,然后又通过属性文件的方式配置Feign,属性文件中Feign的配置会覆盖Java代码的配置。但是可以配置feign.client.default-to-properties=false来改变Feign配置生效的优先级。
本文暂时没有评论,来添加一个吧(●'◡'●)