OpenFeign是什么
Feign是一个声明式的Web Service客户端,是一种声明式、模板化的HTTP客户端。而OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。 OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。
-
1. 可插拔的注解支持,包括Feign注解和JSX-RS注解
-
2. 支持可插拔的HTTP编码器和解码器
-
3. 支持Hystrix和它的Fallback
-
4. 支持Ribbon的负载均衡
-
5. 支持HTTP请求和响应的压缩。
OpenFeign入门
Github地址:https://github.com/maixX05/cloud-openfeign-practice
创建父Pom工程:cloud-openfeign-practice
此工程用于存放所有关于openfeign的示例。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.msr.better</groupId>
<artifactId>cloud-openfeign-practice</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.cloud-version>Hoxton.SR3</spring.cloud-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建模块:cloud-openfeign-hehllo
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
配置文件
application.xml
server:
port: 8010
spring:
application:
name: openfeign-hello
# 日志
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
配置类
@Configuration
public class HelloFeignServiceConfig {
/**
* Logger.Level 的具体级别如下:
* NONE:不记录任何信息
* BASIC:仅记录请求方法、URL以及响应状态码和执行时间
* HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息
* FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
*/
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
serivce
@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
*/
@GetMapping(value = "/search/repositories")
String searchRepo(@RequestParam("q") String queryStr);
}
在上面的HelloFeignService中通过@FeignClient注解手动指定了该接口要访问的URL(https://api.github.com),调用searchGithubRepoByStr方法时,最终会发起GET请求https://api.github.com/search/repositories?q=输入的参数。
controller
@RestController
public class HelloFeignController {
@Autowired
private HelloFeignService helloFeignService;
@GetMapping(value = "/search/github")
public String searchGithubRepoByStr(@RequestParam("searchStr") String searchStr) {
return helloFeignService.searchRepo(searchStr);
}
}
启动类
@SpringBootApplication
@EnableFeignClients
public class OpenFeignHelloApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignHelloApplication.class, args);
}
}
@EnableFeignClients包扫描时,扫描所有@FeignClient。
启动测试
运行启动类之后,在浏览器或者PostMan之类的工具访问http://localhost:8010/search/github?searchStr=spring-cloud

OpenFeign工作原理
-
• 添加@EnableFeignClients注解开启对@FeignClient注解的扫描加载处理。根据Feign Client的开发规范,定义接口并添加@FeiginClient注解
-
• 当程序启动之后,会进行包扫描,扫描所有@FeignClient注解的接口,并将这些信息注入到IOC容器中。当定义的Feign接口被调用时,通过JDK的代理的方式生成具体的RequestTemplate。Feign会为每个接口方法创建一个RequestTemplate对象。该对象封装了HTTP请求需要的所有信息,例如请求参数名、请求方法等信息。
-
• 然后由RequestTemplate生成Request,把Request交给Client去处理,这里的Client可以是JDK原生的URLConnection、HttpClient或Okhttp。最后Client被封装到LoadBalanceClient类,看这个类的名字既可以知道是结合Ribbon负载均衡发起服务之间的调用,因为在OpenFeign中默认是已经整合了Ribbon了。
OpenFiegn的基础功能
剖析@FeignClient注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {...}
从FeignClient的注解可以看得出,ElementType.TYPE
说明FeignClient的作用目标是接口。其常用的属性如下:
-
• name:执行FeignClient的名称,如果项目中使用Ribbon,name属性会作为微服务的名称,用作服务发现。
-
• url:url一般用于调试,可以手动指定@FeignClient调用的地址
-
• decode404:当发生404错误时,如果该字段为true,会调用decoder进行解码,否则抛出FeignException。
-
• configuration:Feigin配置类,可自定义Feign的Encode,Decode,LogLevel,Contract。
-
• fallback:定义容错的类,当远程调用的接口失败或者超时的时候,会调用对应接口的容错罗杰,fallback执行的类必须实现@FeignClient标记的接口。在OpenFeign的依赖中可以发现,集成Hystrix。
-
• fallbackFactory:工厂类,用于生成fallback类实例,通过此属性可以实现每个接口通用的容错逻辑,以达到减少重复的代码。
-
• path:定义当前FeignClient的统一前缀。
OpenFeign开始GZIP压缩
OpenFeign支持对请求和响应进行GZIP压缩,以此来提供通信效率。只需在配置文件中配置即可,比较简单。
server:
port: 8011
spring:
application:
name: openfeign-gzip
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
feign:
# 压缩配置
compression:
request:
enabled: true
# 配置压缩支持的MIME TYPE
mime-types: text/xml,application/xml,application/json
min-request-size: 2048 # 配置压缩数据大小的下限
response:
enabled: true # 配置响应GZIP压缩
等价的properties配置
feign.compression.request.enabled=true
# 配置压缩支持的MIME TYPE
feign.compression.request.mime-types=text/xml,application/xml,application/json
# 配置压缩数据大小的下限
feign.compression.request.min-request-size=2048
# 配置响应GZIP压缩
feign.compression.response.enabled=true
支持属性文件配置
对单个特定名称的FeignClient进行配置
@FeignClientde的配置信息可以通过配置文件的方式来配置
server:
port: 8011
spring:
application:
name: openfeign-gzip
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
feign:
# 压缩配置
compression:
request:
enabled: true
# 配置压缩支持的MIME TYPE
mime-types: text/xml,application/xml,application/json
min-request-size: 2048 # 配置压缩数据大小的下限
response:
enabled: true # 配置响应GZIP压缩
client:
config:
# 需要配置的FeignName
github-client:
# 连接超时时间
connectTimout: 5000
# 读超时时间
readTimeut: 5000
# Feign的日志级别
loggerLevel: full
# Feign的错误解码器
errorDecode: com.example.SimpleErrorDecoder
# 设置重试
retryer: com.example.SimpleRetryer
# 拦截前
requestInterceptors:
- com.example.FirstInterceptor
- com.example.SecondInterceptor
decode404: false
# Feign的编码器
encoder: com.example.SimpleEncoder
# Feign的解码器
decoder: com.example.SimpleDecoder
# Feign的contract配置
contract: com.example.SimpleContract
作用于所有FeignClient的配置
在@EnableFeignClients注解上有一个defaultConfiguration属性,可以将默认设置写成一个配置类,例如这个类叫做DefaultFeignClientConfiguration。
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = DefaultFeignClientConfiguration.class)
public class FeignClientConfigApplication{
SpringApplication.run(FeignClientConfigApplication.class, args);
}
同时也可以在配置文件中配置
feign:
client:
config:
default:
# 连接超时时间
connectTimout: 5000
# 读超时时间
readTimeut: 5000
# Feign的日志级别
loggerLevel: full
...
但是如果以上两种方式(在配置文件和在注解中配置FeignClient的全局配置),最后配置文件会覆盖注解上执行配置类的方式。但是可以在配置文件中添加feign.client.default-to-properties=false
来改变Feigin配置的优先级。
FeignClient开启日志
其实在上面的就已经是配置了FeignClient的日志了。Feign为每一个Feign都提供了一个fegin.Logger实例。可以在配置中开启日志输出,开启的步骤也很简单。
第一步:在配置文件中配置日志输出
logging:
level:
# 指定那个FeignClient接口的请求需要输出日志,以及日志级别
com.msr.better.feign.service.HelloFeignService: debug
第二步:通过Java代码的方式在主程序入口配置日志Bean
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
又或者通过配置类配置,并在@FeignClient注解中执行改配置类。
@Configuration
public class HelloFeignServiceConfig {
/**
* Logger.Level 的具体级别如下:
* NONE:不记录任何信息
* BASIC:仅记录请求方法、URL以及响应状态码和执行时间
* HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息
* FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
*/
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
FeignClient超时配置
Feign的调用分为两层,Ribbon的调用和Hystrix的调用。但是高版本的Hystrix默认是关闭的。一般出现想这样的异常:Read timed out executing POST http://***
,是由Ribbon引起,这样可以适当得调大一下Ribbon的超时时间
ribbon:
ConnectTimeout: 2000
ReadTimeout: 5000
HystrixRuntimeException: XXX timed -out and no fallback available .这就是Hystrix的超时报错
feign:
hystrix:
enabled: true
# 设置hystrix超时时间
hystrix:
shareSecurityContext: true
command:
default:
circuitBreaker:
sleepWindowinMilliseconds: 10000
forceClosed: true
execution:
isolation:
thread:
timeoutinMilliseconds: 10000
最后
可关注我的微信公众号

原文始发于微信公众号(杂食的程序员):Spring Cloud OpenFeign基础入门
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/281298.html