文章目录
OpenFeign概述
OpenFeign是什么
Spring Cloud OpenFeign是Spring Cloud生态系统中的一部分,它提供了一种声明式的、简化的方式来调用RESTful服务。它使得开发人员可以使用注释和接口定义来描述对服务的请求,并且它可以自动地生成客户端代码来处理这些请求。
使用Spring Cloud OpenFeign,开发人员可以通过简单地定义接口来调用远程服务。开发人员只需要使用Spring MVC的注释,例如@GetMapping和@PostMapping,定义接口,OpenFeign就可以自动地将这些接口映射到RESTful服务。开发人员还可以使用Fallback功能来处理远程服务的失败。
Spring Cloud OpenFeign还提供了一些其他功能,例如服务发现和负载均衡。这些功能可以与Eureka、Consul、Zookeeper等服务注册中心集成,以便在分布式系统中使用。
为什么有了RestTemplate还要OpenFeign来调用
前几章我们通过了Ribbon+RestTemplate实现了服务的远程调用,但是有很多缺陷,OpenFeign在此基础上做了一些封装,使其有了更好的优势
- 声明式的Web服务客户端:使用OpenFeign,开发人员可以使用注释来定义对RESTful服务的请求,从而避免编写大量的样板代码。这使得代码更加简洁、易于理解和维护。
- 更高的抽象级别:OpenFeign的抽象级别比RestTemplate更高。开发人员只需编写简单的接口并使用注释来定义请求,而不必关心底层的HTTP请求和响应处理。这使得代码更容易编写、测试和维护。
- 自动映射RESTful服务:OpenFeign可以自动地将接口映射到RESTful服务,减少了开发人员需要编写的样板代码数量。这使得代码更加简单、易于维护,并且可以减少错误。
- 支持断路器模式:OpenFeign可以与Hystrix等断路器库集成,以便在远程服务失败时提供回退处理。这使得系统更加健壮、可靠,并且可以保证服务的高可用性。
- 支持编码和解码:OpenFeign支持多种编码和解码格式,例如JSON、XML等。这使得数据传输更加灵活,并且可以支持更多的应用场景。
Feign和OpenFeign两者区别
-
底层实现:OpenFeign底层依赖于Spring Cloud和Spring MVC,而Feign底层依赖于Netflix的开源项目。
-
注解支持:OpenFeign支持Spring MVC注解,例如@RequestParam、@RequestBody等,而Feign则需要使用自己的注解。
-
自定义契约:OpenFeign可以通过实现自定义契约来扩展和定制化,而Feign则没有这样的扩展方式。
-
断路器支持:OpenFeign集成了Hystrix,而Feign需要单独引入Hystrix来实现断路器支持。
-
拦截器支持:OpenFeign提供了更加灵活和全面的HTTP请求和响应拦截器支持,可以对请求和响应进行更加细粒度的处理,而Feign的拦截器支持相对较少。
OpenFeign在底层实现、注解支持、自定义契约、断路器支持和拦截器支持等方面与Feign有所不同。根据具体的业务需求和开发背景,选择合适的框架来进行开发和调用RESTful服务。
OpenFeign使用
demo搭建
新建一个调用服务module,还是参照auth服务,具体的服务调用我们从RestTemplate换成OpenFeign
- 复制一个auth服务
- pom.xml
区别主要是添加了openfeign的依赖
<dependencies>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--web-->
<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>
<!--一般基础通用配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- application.yml
直接复制一份auth服务的不变
server:
port: 9002
spring:
application:
name: lf-auth
eureka:
instance:
# 配置eureka的状态显示
hostname: localhost
instance-id: ${
eureka.instance.hostname}:${
spring.application.name}:${
server.port}
client:
#表示是否将自己注册进EurekaServer默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版
启动类
主要是添加@EnableFeignClients注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class FeignAuthApplication {
public static void main(String[] args) {
SpringApplication.run(FeignAuthApplication.class,args);
}
}
service接口
新增注解@FeignClient通过业务逻辑接口+@FeignClient配置调用LF-USER服务
@FeignClient(value = "LF-USER")
public interface AuthService {
@GetMapping("/user/info/{username}")
String getUserInfo(@PathVariable("username") String username);
}
controller
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
AuthService authService;
@PostMapping("login")
public String login(@RequestBody String name)
{
return authService.getUserInfo(name);
}
}
测试
先启动服务,确认eureka服务端,和各个服务注册成功。
调用接口测试成功
Feign超时
如下图,官网说明,OpenFeign是有默认的超时时间的,分别是连接超时时间和读超时时间
查看源码默认连接超时时间10s和读超时时间 60s;
测试超时时间
我们测试下,在9001端口的user服务端加一个3s延时。 并且只启动这个服务端。
结果会发现报错超时了。
为什么我们只设置了睡眠3秒就报超时呢?远没有达到上面的连接超时和读超时时间。其实 openFeign 集成了 Ribbon,Ribbon 的默认超时连接时间、读超时时间都是是1秒,源码如下图:
如果没有设置openFeign 的默认超时时间就会取Ribbon的超时时间
设置超时时间
设置Ribbon的超时时间(不推荐)
修改lf-feign-auth服务的yml文件
ribbon:
# 值的是建立链接所用的时间,适用于网络状况正常的情况下, 两端链接所用的时间
ReadTimeout: 5000
# 指的是建立链接后从服务器读取可用资源所用的时间
ConectTimeout: 5000
测试成功:
设置feign的超时时间(推荐)
feign:
client:
config:
## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
default:
connectTimeout: 5000
readTimeout: 5000
同样测试成功:
为什么推荐设置feign的超时时间
在 OpenFeign 中,超时时间是由客户端的配置文件指定的。在这个配置文件中,可以为每个服务实例设置单独的超时时间。这样可以更加精确地控制超时时间,因为不同的服务实例可能具有不同的响应时间。如果在 Ribbon 中设置超时时间,则可能会将请求分配到响应时间较长的服务实例上,从而导致请求超时,而无法得到及时的响应。
此外,如果使用 Ribbon 进行负载均衡时,超时时间还会受到 Ribbon 的重试机制的影响。在默认情况下,Ribbon 会进行 5 次重试,每次重试之间的间隔时间逐渐加长。如果设置了超时时间,但是请求一直被重试,那么可能会导致超时时间被延长,从而影响应用程序的性能和稳定性。
因此,为了更加精确地控制超时时间,并避免受到 Ribbon 的重试机制的影响,建议在 OpenFeign 中设置超时时间。
替换的 HTTP 客户端:
openFeign 默认使用的是 JDK 原生的 URLConnection 发送 HTTP 请求,没有连接池,但是对每个地址会保持一个长连接,即利用 HTTP 的 persistence connection。在生产环境中,通常不使用默认的 http client,通常有两种选择:使用 ApacheHttpClient 或者 OkHttp,两者各有千秋
修改pom.xml
添加如下依赖
<!-- 使用 Apache HttpClient 替换 Feign原生httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
OpenFeign日志打印功能
openFeign 虽然提供了日志增强功能,但默认是不显示任何日志的,不过开发者在调试阶段可以自己配置日志的级别。
openFeign 的日志级别如下:
- NONE:默认的,不显示任何日志;
- BASIC:仅记录请求方法、URL、响应状态码及执行时间;
- HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;
- FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
配置日志
自定义一个配置类,在其中设置日志级别,如下:
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
修改application.yml
添加配置
logging:
level:
# feign日志以什么级别监控哪个接口
com.lufei.springcloud.service: debug
测试效果
日志中详细的打印出了请求头、请求体的内容。