Spring Cloud 中Feign组件

为什么要用?

问: 使用了ribbon(负载均衡)后,有没有什么问题?不方便的地方呢?

答: 使用ribbon后,还是需要拼接请求路劲,如果请求参数有多个的话,这时拼接请求字符串就会效率低下,

而feign就很好的解决了此问题

什么是feign?

Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

由于Netflix为我们提供的框架:Feign,已经闭源了,但是Spring Cloud推出了一款新的框架openfeign

Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认实现了负载均衡的效果。

如何使用?

在这里插入图片描述
由于feign接口是可复用的,所以我们可以将其抽离出来单独编写,减少代码的冗余

  1. 创建feign-consumer模块(服务消费者)

    • 引入依赖

      <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <!--后面编写的处理服务接口-->
              <dependency>
                  <groupId>com.bjpowernode</groupId>
                  <artifactId>feign_interface</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
              <!--nacos客户端-->
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
          </dependencies>
      
    • 配置文件

      server:
        port: 80
      spring:
        cloud:
          nacos:
            discovery:
              server-addr: 192.168.255.132:8848 #注册中心的地址
        application:
          name: feign-consumer #注册到注册中心的名字
      
    • 模拟请求

      @RestController
      @RequestMapping("/consumer")
      public class ConsumerController {
      
          @Autowired
          private UserFeign userFeign;//代理类
      
          @RequestMapping("/getUserById/{id}")
          public User getUserById(@PathVariable Integer id){
              System.out.println(userFeign.getClass());
              return userFeign.getUserById(id);
          }
      
          @RequestMapping("/deleteUserById")
          public User deleteUserById(Integer id){
              return userFeign.deleteUserById(id);
          }
      
          @RequestMapping("/addUser")
          public User addUser(User user){
              return userFeign.addUser(user);
          }
      }
      
  2. 创建feign-provider模块(服务提供者)

    • 引入依赖

      <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <!--后面编写的处理服务接口-->
              <dependency>
                  <groupId>com.bjpowernode</groupId>
                  <artifactId>feign_interface</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
              <!--nacos客户端-->
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
          </dependencies>
      
    • 配置文件

      server:
        port: 9090
      spring:
        cloud:
          nacos:
            discovery:
              server-addr: 192.168.255.132:8848 #nacos服务的地址
        application:
          name: feign-provider #向注册中心注册的名字
      
    • 模拟响应服务

      @Service
      public class UserServiceImpl implements UserService {
      
          @Override
          public User getUserById(Integer id) {        
              return new User(id,"User-1",18);
          }
      
          @Override
          public User deleteUserById(Integer id) {
              return new User(id,"删除了User-1",18);
          }
      
          @Override
          public User addUser(User user) {
              user.setName("新增了User-1");
              return user;
          }
      }
      
  3. 创建feign_interface模块

    • 引入依赖

      <dependencies>
              <!--Spring Cloud OpenFeign Starter -->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-openfeign</artifactId>
              </dependency>
              <!--工具模块-->
              <dependency>
                  <groupId>com.bjpowernode</groupId>
                  <artifactId>springcloud_common</artifactId>
              </dependency>
          </dependencies>
      
    • 编写一个接口在feign包下

      @FeignClient("feign-provider")
      @RequestMapping("/provider")
      public interface UserFeign {
      
          @RequestMapping("/getUserById/{id}")//拼接url
          public User getUserById(@PathVariable("id") Integer id);//restful形式拼接参数
      
          @RequestMapping("/deleteUserById")//拼接url
          User deleteUserById(@RequestParam("id") Integer id);//?形式拼接参数,?id=250
      
          @RequestMapping("/addUser")
          User addUser(@RequestBody User user);//pojo--->json
      }
      
      

注解

消费者中:

@EnableFeignClients//开启feign注解的扫描

为什么写在了feign-consumer类的启动类上,而不是feign_interface类中?

因为在feign-consumer中引入了feign_interface,这就相当于把feign_interface中的代码写入了feign-consumer,所有直接在feign-consumer中使用,连同feign_interface中也使用了此注解

feign_interface接口中:

在接口中我们看到有一些熟悉和陌生的注解,但在接口中的注解都和原先的意思有所不同

  1. 在类上

    @FeignClient(“feign-provider”)

    处理此类请求的服务名

  2. 在方法上

    以下注解含义仅在使用了@FeignClient注解后表示,并要将参数明文指定出来

    • @RequestMapping

      拼接请求路径

      注:在

    • @PathVariable

      路径方式发送请求参数

    • @RequestParam

      ?拼接方式发送请求参数

    • @RequestBody

      将对象转化为Json串形式发送请求参数

      如:实体类(pojo),数组,集合

feign实现原理

​ 1、将feign接口的代理类扫描到Spring容器中:
​ @EnableFeignClients开启feign注解扫描:FeignClientsRegistrar.registerFeignClients()扫描被 @FeignClient标识的接口生成代理类,
​ 并把接口和代理类交给Spring的容器管理。
​ 2、为接口的方法创建RequestTemplate
​ 当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url,参数)
​ 3、发出请求
​ 代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求

feign优化

feign发送的是Http请求,实际不如dubbox发送请求快,那我们为什么还要用用feign而不用dubbox呢?

原因就是feign是可以优化滴!

那么都有哪些可以优化的呢?

有以下四点可以优化:

由于feign_interface没有配置文件,全部在feign-consumer配置文件中设置,原因是feign-consumer引入了feign_interface,在feign-consumer配置,等同于在feign_interface中配置,即在feign-consumer配置文件中修改即可

1、开启feign日志

开启feign日志时,还需开启系统日志!

feign的日志级别一共有四种:

  1. NONE:没有日志记录

  2. BASIC:记录请求方法、URL以及响应状态代码和执行时间

  3. HEADERS:记录基本信息以及请求和响应头信息

  4. FULL:记录基本信息以及请求和响应头信息、请求和响应体信息

feign:
  client:
    config:
      feign-provider:  #开启日志的服务 default:表示所有服务
        loggerLevel: full #feign日志的级别
logging:
  level:
    com.bjpowernode.feign: debug #设置单个包下的日志输出级别

效果如下
在这里插入图片描述

​ 2、feign超时优化

处理请求,当某段代码负载过高,运行超时,导致调用超时异常,我们可以通过延长请求连接时间进行优化

​ 1、方式一:

设置ribbon连接请求与处理请求超时时间,单位为毫秒

ribbon:
  ConnectTimeout: 5000 #请求连接的超时时间
  ReadTimeout: 5000 #请求处理的超时时间

​ 2、方式二:

设置feign连接请求与处理请求超时时间,单位为毫秒

feign:
  client:
    config:
      feign-provider:
        ConnectTimeout: 5000 #请求连接的超时时间
        ReadTimeout: 5000 #请求处理的超时时间

​ 3、http连接池

两台服务器建立HTTP连接的过程涉及到多个数据包的交换,很消耗时间(三次握手四次分手)。采用HTTP连接池可以节约大量的时间。

Feign的HTTP客户端支持3种框架:HttpURLConnection、HttpClient、OkHttp。

Feign 默认是采用HttpURLConnection ,每次请求都会建立、关闭连接。

引入依赖即可,默认设置

        <dependency>
		    <groupId>io.github.openfeign</groupId>
		    <artifactId>feign-httpclient</artifactId>
		</dependency>

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

​ 4、gzip压缩

gzip 是一种数据格式,使用 Gzip 压缩一个纯文本文件时,大约可以减少 70% 以上的文件大小。

server:
  port: 80
  compression:
    enabled: true #开启gzip压缩

默认支持格式

{"text/html", "text/xml", "text/plain", "text/css", "text/javascript", "application/javascript", "application/json", "application/xml"}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值