OpenFeign

发布于 2022-04-19  2.58k 次阅读


一,OpenFeign的简介

Feign是一个声明式WebService客户端,使用Feign能让编写Web Service客户端更加简单

   它的使用方法是定义一个服务接口然后在上面添加注解,Feign也支持可插拔式的编码和解码器,Spring Cloud对Feign进行封装,使其支持了Spring MVC标准注解和HttpMessageConvers,Feign可以与Eureka和Ribbon组合使用以支持负载均衡

Feign的作用:Feign旨在使编写java http客户端变得简单

   在使用Ribbon+RestTemplate时,利用RestTemplate对http请求进行封装处理,形成了一套模板化的调用方法,但是在实际开发中,由于服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每一个微服务自行封装一些客户端类来包装这些依赖服务的调用,所以Feign在此基础上做进一步封装,由它来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式配置它(在Dao接口上标准Mapper注解,现在是一个微服务接口上标注一个Feign注解即可),完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量

Feign集成Ribbon:利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

OpenFeign是对Feign的进一步增强,在本质上没有什么差别:

Feign
OpenFeign
Feign是Spring Cloud组件中的一个轻量级RestFul的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务,Feign的使用方式:使用Feign的注解定义接口,调用这个接口就可以调用服务注册中心的服务
OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如RequestMapping等,OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.3.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>3.0.1</version>
</dependency>

二,OpenFeign的使用

一,使用演示

① maven依赖

<properties>
    <cloud-springbootweb>2.5.5</cloud-springbootweb>
    <cloud-springbootactuator>2.5.5</cloud-springbootactuator>
    <cloud-devotools>2.5.5</cloud-devotools>
    <cloud-lombok>1.18.2</cloud-lombok>
</properties>

<dependencies>
    <dependency>
        <groupId>com.cloud.commons</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>${cloud-springbootweb}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
        <version>${cloud-springbootactuator}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>${cloud-devotools}</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${cloud-lombok}</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

② application配置

server:
  port: 8085

spring:
  application:
    name: cloud-consumer-openfeign-order

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka1.com:9090/eureka/,http://eureka2.com:9091/eureka/

③ Main方法

@SpringBootApplication
@EnableFeignClients//标注使用Feign进行服务调用,这个注解有@EnableEurekaClient的功能
public class OpenFeignMain {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignMain.class,args);
    }
}

④OpenFeign接口

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVER" )//value为连接的服务名称
public interface PaymentFeignService {
    @RequestMapping("/payment/select/{id}")//服务应用程序里面对应的接口地址,底层通过Ribbon进行调用
    public CommonResult<payment> select(@PathVariable("id") int id);
}

⑤ Controller 

@RestController
@Slf4j
public class OrderFeignController {

    @Resource//注入OpenFeign接口
    PaymentFeignService feignService;

    @RequestMapping("/consumer/payment/select/{id}")
    public CommonResult<payment> select(@PathVariable("id") int id){

        return feignService.select(id);
    }
}

测试:

OpenFeign调用过程:

二,OpenFeign的超时控制和日志增强

一,OpenFeign的超时控制

默认Feign客户端只等待1秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待,直接返回报错,为了避免这种情况,有时候我们需要设置Feign客户端超时控制

超时演示:

① 服务提供端

@RequestMapping("time")
public String timeout(){

    try {
        TimeUnit.SECONDS.sleep(10);
    }catch (InterruptedException e){e.printStackTrace();}
    return server;
}

② OpenFeign接口

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVER" )//value为连接的服务名称
public interface PaymentFeignService {
    @RequestMapping("/time")
    public String timeout();
}

③ 服务消费端

@RestController
@Slf4j
public class OrderFeignController {

    @Resource//注入OpenFeign接口
    PaymentFeignService feignService;

    @RequestMapping("/payment/time")
    public String timeout(){
        return feignService.timeout();
    }}

测试:

 

设置超时时间:

ribbon: #OpenFeign底层使用Ribbon实现,所以配置Ribbon即可
  ReadTimeout: 5000 #指建立连接所用超时时间
  ConnectTimeout: 5000 #指从服务器获取服务超时时间
重新测试:

二,OpenFeign的日志增强

Feign提供了日志打印功能,可以提供配置来调整日志级别,从而了解Feign中Http请求细节

本质上就是对Feign接口的调用情况进行监控和输出

日志级别:

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

步骤:

① 配置类

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

② application配置

logging:
  level: #feign日志以什么级别监控那个接口
    com.cloud.service.PaymentFeignService: debug

测试:


路漫漫其修远兮,吾将上下而求索