Spring Cloud OpenFeign 详解

Spring Cloud OpenFeign

知识点:

  1. OpenFeign介绍
  2. 使用方法
  3. 4个特点(Gzip、灵活Logger、替换HttpUrlConnect、超时控制)
  4. 原理分析(启动的EnbaleFeignClients,扫描FeignClient,注入Spring bean中的Factorybean 代理bean,调用的时候直接执行)

1、介绍

OpenFeign源于Netflix的Feign,是http通信的客户端。屏蔽了网络通信的细节,直接面向接口的方式开发,让开发者感知不到网络通信细节。 所有远程调用,都像调用本地方法一样完成!

OpenFeign 是 Spring Cloud 对 Feign 的二次封装,它具有 Feign 的所有功能,并在 Feign 的基础上增加了对 Spring MVC 注解的支持,例如 @RequestMapping、@GetMapping 和 @PostMapping 等。

OpenFeign 对 Ribbon进行了集成,利用 Ribbon 维护了一份可用服务清单,并通过 Ribbon 实现了客户端的负载均衡。

  • Openfeign源于Netflix的Feign,http通信的客户端。屏蔽了网络通信的细节。让所有的调用都想本地调用一样完成。
  • 支持Spring MVC注解。
  • 集成了Ribbon实现了客户端的负载均衡。

1.1、OpenFeign 常用注解

注解 说明
@FeignClient 该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。
@EnableFeignClients 该注解用于开启 OpenFeign 功能(一般使用在SpringBoot启动类上),当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。
@RequestMapping Spring MVC 注解,在 Spring MVC 中使用该注解映射请求,通过它来指定控制器(Controller)可以处理哪些 URL 请求,相当于 Servlet 中 web.xml 的配置。
@GetMapping Spring MVC 注解,用来映射 GET 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.GET) 。
@PostMapping Spring MVC 注解,用来映射 POST 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.POST) 。

2、使用方法

创建项目provider-api,作为OpenFeign接口公共Api

引入pom依赖

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

创建Api接口

public interface IPromotionService {
    @GetMapping("/promotion")
    public String promotion();
}

创建feignClient接口

@FeignClient(name = "marking-service") // 这里FeignClient注解会被扫描
public interface IPromotionServiceClient extends IPromotionService {
}

创建项目provider-service

引入pom依赖


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>

 <dependency>
     <groupId>com.fangergroupId>
     <artifactId>provider-apiartifactId>
dependency>

创建API接口实现

@Slf4j
@RestController
@RequestMapping("/promotion")
public class PromotionController implements IPromotionService {
    @GetMapping
    public String promotion(){
        return "promotion-info SUCCESS";
    }
}

application.properties

server.port=9091
spring.application.name=provider-service
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

创建consumer-service

consumer-service是OpenFeign接口的调用方

引入pom依赖


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-ribbonartifactId>
    <version>2.2.9.RELEASEversion>
dependency>

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

 <dependency>
     <groupId>com.fangergroupId>
     <artifactId>provider-apiartifactId>
dependency>

启动类配置

// 开启OpenFeign,并配置扫描路径,provider-api中feignClient接口的类路径
@EnableFeignClients(basePackages = "com.fanger.mall.feignclient") 
@SpringBootApplication
public class ConsumerServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerServiceApplication.class, args);
    }
}

application.properties

server.port=8080
spring.application.name=ConsumerService
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

Controller接口

@Slf4j
@RestController
public class PromotionController {

    // 这里注入代理类
    @Autowired
    IPromotionService iPromotionService;

    @PostMapping("/promotion")
    public String login(){
       	// 这里直接类似本地调用的方式来执行
        return iPromotionService.promotion();
    }
}

3、OpenFeign的特性

3.1、Gzip压缩

开启压缩可以有效节约网络资源,但是会增加CPU压力,建议把最小压缩的文档大小适度调大一点

#开启压缩可以有效节约网络资源,但是会增加CPU压力,建议把最小压缩的文档大小适度调大一点
#开启gzip 压缩协议
feign.compression.request.enabled=false
#响应也开启gzip压缩传输协议
feign.compression.response.enabled=true
#最小压缩文件大小为2048m
feign.compression.request.min-request-size=2048
#请求数据格式
feign.compression.request.mime-types=text/xml, application/xml, application/json

3.2、Feign日志配置

a. 创建config类

@Configuration
public class FeignLogConfig {
    @Bean
    Logger.Level feignLogger(){
        Logger.Level full = Logger.Level.FULL; //全部日志
        Logger.Level none = Logger.Level.NONE; //不记录日志
        Logger.Level basic = Logger.Level.BASIC;  //除了headers日志
        Logger.Level headers = Logger.Level.HEADERS; //headers 日志
        return full;
    }
}

b.需要记录日志处引用FeignLogConfig 类

@FeignClient(name = "eureka-product-service",configuration = FeignLogConfig.class)
public interface IHelloControllerFeign {

    @GetMapping("/hello")
    String sayHello();
}

c. application.properties 配置需要记录日志文件的日志级别

#设置feign日志级别
logging.level.[com.example.demo.service.IHelloControllerFeign]=debug

3.3、替换默认的底层通信

默认远程访问协议为jdk自带的sun.net.www.protocol.http.HttpURLConnection效率低,可改为okHttp

a.添加OKhttp依赖

<dependency>
        <groupId>io.github.openfeigngroupId>
        <artifactId>feign-okhttpartifactId>
 dependency>

b.application.properties 配置,关闭默认的sun.net.www.protocol.http.HttpURLConnection,开启okhttp

feign.httpclient.enable=false
feign.okhttp.enable=true

3.4、超时控制

OpenFeign默认超时时间为1s,超过1s就会返回错误页面。如果我们的接口处理业务确实超过1s,就需要对接口进行超时配置,如下:

ribbon: #设置feign客户端连接所用的超时时间,适用于网络状况正常情况下,两端连接所用时间
  ReadTimeout: 1000 #指的是建立连接所用时间
  ConnectTimeout: 1000 #指建立连接后从服务读取到可用资源所用时间

4、工作原理分析

Spring Cloud OpenFeign 详解_第1张图片

Feign 的工作流程:

  1. SpringBoot 应用启动时, 由针对 @EnableFeignClient 这一注解的处理逻辑触发程序扫描 classPath中所有被@FeignClient 注解的类, 这里以 DemoService 为例, 将这些类解析为 BeanDefinition 注册到 Spring 容器中
  2. Sping 容器在为某些用的 Feign 接口的 Bean 注入 DemoService 时, Spring 会尝试从容器中查找 DemoService 的实现类
  3. 由于我们从来没有编写过 DemoService 的实现类, 上面步骤获取到的 DemoService 的实现类必然是 feign 框架通过扩展 spring 的 Bean 处理逻辑, 为 DemoService 创建一个动态接口代理对象, 这里我们将其称为 DemoServiceProxy 注册到spring 容器中。
  4. Spring 最终在使用到 DemoService 的 Bean 中注入了 DemoServiceProxy 这一实例。
  5. 当业务请求真实发生时, 对于 DemoService 的调用被统一转发到了由 Feign 框架实现的 InvocationHandler 中, InvocationHandler 负责将接口中的入参转换为 HTTP 的形式, 发到服务端, 最后再解析 HTTP 响应, 将结果转换为 Java 对象, 予以返回。

Spring Cloud OpenFeign工作原理解析

你可能感兴趣的:(Spring,Cloud,spring,cloud)