Spring Cloud学习笔记【服务调用-OpenFeign】

文章目录

  • OpenFeign概述
    • OpenFeign是什么
    • 为什么有了RestTemplate还要OpenFeign来调用
    • Feign和OpenFeign两者区别
  • OpenFeign使用
    • demo搭建
    • 测试
  • Feign超时
    • 测试超时时间
    • 设置超时时间
      • 设置Ribbon的超时时间(不推荐)
      • 设置feign的超时时间(推荐)
      • 为什么推荐设置feign的超时时间
  • 替换的 HTTP 客户端:
  • OpenFeign日志打印功能
    • 配置日志
    • 测试效果

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服务
    Spring Cloud学习笔记【服务调用-OpenFeign】_第1张图片
  • pom.xml
    区别主要是添加了openfeign的依赖
<dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        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服务端,和各个服务注册成功。
Spring Cloud学习笔记【服务调用-OpenFeign】_第2张图片

调用接口测试成功
Spring Cloud学习笔记【服务调用-OpenFeign】_第3张图片

Feign超时

如下图,官网说明,OpenFeign是有默认的超时时间的,分别是连接超时时间和读超时时间
Spring Cloud学习笔记【服务调用-OpenFeign】_第4张图片
查看源码默认连接超时时间10s和读超时时间 60s;
在这里插入图片描述

测试超时时间

我们测试下,在9001端口的user服务端加一个3s延时。 并且只启动这个服务端。
Spring Cloud学习笔记【服务调用-OpenFeign】_第5张图片
结果会发现报错超时了。
Spring Cloud学习笔记【服务调用-OpenFeign】_第6张图片
为什么我们只设置了睡眠3秒就报超时呢?远没有达到上面的连接超时和读超时时间。其实 openFeign 集成了 Ribbon,Ribbon 的默认超时连接时间、读超时时间都是是1秒,源码如下图:

Spring Cloud学习笔记【服务调用-OpenFeign】_第7张图片
如果没有设置openFeign 的默认超时时间就会取Ribbon的超时时间

设置超时时间

设置Ribbon的超时时间(不推荐)

修改lf-feign-auth服务的yml文件

ribbon:
  # 值的是建立链接所用的时间,适用于网络状况正常的情况下, 两端链接所用的时间
  ReadTimeout: 5000
  # 指的是建立链接后从服务器读取可用资源所用的时间
  ConectTimeout: 5000

测试成功:Spring Cloud学习笔记【服务调用-OpenFeign】_第8张图片

设置feign的超时时间(推荐)

feign:
  client:
    config:
      ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
      default:
        connectTimeout: 5000
        readTimeout: 5000

同样测试成功:
Spring Cloud学习笔记【服务调用-OpenFeign】_第9张图片

为什么推荐设置feign的超时时间

在 OpenFeign 中,超时时间是由客户端的配置文件指定的。在这个配置文件中,可以为每个服务实例设置单独的超时时间。这样可以更加精确地控制超时时间,因为不同的服务实例可能具有不同的响应时间。如果在 Ribbon 中设置超时时间,则可能会将请求分配到响应时间较长的服务实例上,从而导致请求超时,而无法得到及时的响应。

此外,如果使用 Ribbon 进行负载均衡时,超时时间还会受到 Ribbon 的重试机制的影响。在默认情况下,Ribbon 会进行 5 次重试,每次重试之间的间隔时间逐渐加长。如果设置了超时时间,但是请求一直被重试,那么可能会导致超时时间被延长,从而影响应用程序的性能和稳定性。

因此,为了更加精确地控制超时时间,并避免受到 Ribbon 的重试机制的影响,建议在 OpenFeign 中设置超时时间。

替换的 HTTP 客户端:

openFeign 默认使用的是 JDK 原生的 URLConnection 发送 HTTP 请求,没有连接池,但是对每个地址会保持一个长连接,即利用 HTTP 的 persistence connection。在生产环境中,通常不使用默认的 http client,通常有两种选择:使用 ApacheHttpClient 或者 OkHttp,两者各有千秋
修改pom.xml
添加如下依赖

 
        <dependency>
            <groupId>org.apache.httpcomponentsgroupId>
            <artifactId>httpclientartifactId>
        dependency>
        <dependency>
            <groupId>io.github.openfeigngroupId>
            <artifactId>feign-httpclientartifactId>
        dependency>

OpenFeign日志打印功能

openFeign 虽然提供了日志增强功能,但默认是不显示任何日志的,不过开发者在调试阶段可以自己配置日志的级别。
openFeign 的日志级别如下:

  • NONE:默认的,不显示任何日志;
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间;
  • HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;
  • FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。

配置日志

自定义一个配置类,在其中设置日志级别,如下:
Spring Cloud学习笔记【服务调用-OpenFeign】_第10张图片

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

修改application.yml
添加配置

logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.lufei.springcloud.service: debug

测试效果

Spring Cloud学习笔记【服务调用-OpenFeign】_第11张图片
日志中详细的打印出了请求头、请求体的内容。

你可能感兴趣的:(微服务,springcloud,java后端,spring,cloud,Feign,OpenFeign,java)