OpenFeign介绍以及使用

介绍

OpenFeign 是一个声明式的 Web 服务客户端,用于简化在 Java 应用中调用 HTTP API 的过程,在 Spring Cloud 体系里被广泛应用,它有以下关键特性:

  • 声明式调用:基于注解,开发人员只需定义接口并添加注解,就能轻松描述对远程服务的 HTTP 请求,无需手动编写大量重复的 HTTP 客户端代码,如使用@FeignClient注解来指定要调用的服务名称。
  • 集成与适配:它能与 Spring Cloud 的服务发现机制(如 Eureka、Consul 等)无缝集成,调用远程服务时,借助服务发现找到目标服务实例的实际网络地址,开发者不用关心服务实例的具体位置和动态变化。同时,OpenFeign 可以方便地整合 Ribbon 实现客户端负载均衡,自动在多个服务实例间分摊请求流量。
  • 可定制化:提供了丰富的编码器和解码器,支持多种数据格式的传输,例如 JSON、XML 等。此外,还允许自定义请求拦截器,可在请求发送前添加公共的请求头、鉴权信息,满足复杂业务场景下的定制需求。
  • 熔断降级:可以结合 Hystrix 等熔断器框架,当被调用的远程服务出现故障、响应超时等异常情况时,快速触发熔断机制,返回预设的兜底数据,避免级联故障,保障整个微服务系统的稳定性。

使用原因

在我的上一章博客中使用了Nacos对微服务实现了服务的注册以及发现:微服务-注册中心-Nacos,但是发现了一个问题,我们在编写远程调用其他微服务的使用需要很长很复杂的一段http代码,如下:

其实远程调用的几个关键点就是:请求方式、请求路径、请求参数、返回值类型,所以本章用OpenFeign来解决微服务之间的远程调用复杂性,提高开发效率。

OpenFeign使用

这个案例是对上一章微服务-注册中心-Nacos的实例进行改造

1.引入依赖

在CloudDemo2中引入如下依赖:

  <!--openFeign-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>
  <!--负载均衡器-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  </dependency>

删除启动类上的如下代码:

@Bean
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

2.启用OpenFeign

接下来,我们在cloudDemo2的CloudDemo2Application启动类上添加注解,启动OpenFeign功能:

@SpringBootApplication
@EnableFeignClients//开启OpenFeign功能支持
public class CloudDemo2Application {
  public static void main(String[] args) {
    SpringApplication.run(CloudDemo2Application.class);
  }
}

3.编写OpenFeign客户端

在cloudDemo2中创建一个client包,然后在下面创建一个OpenFeign客户端:

package com.waitforme.clouddemo2.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@FeignClient("cloudDemo1") //cloudDemo1微服务模块中配置文件所配置的微服务名
public interface CloudDemo1Client {
  /*
    @FeignClient("cloudDemo1") :声明服务名称
    @GetMapping :声明请求方式
    @GetMapping("/cloudDemo1/list") :声明请求路径
    List<Object> :返回值类型
   */
  @GetMapping("/cloudDemo1/list")
  List<Object> demo1List();
}

编写完上面的代码后,OpenFeign就可以利用动态代理帮我们实现这个方法,并且向http://cloudDemo1/cloudDemo1/list发送一个GET请求,并自动将返回值处理为List<Object>

我们只需要直接调用这个方法,即可实现远程调用了。

4.使用OpenFeign

修改CloudDemo2ServiceImpl代码

package com.waitforme.clouddemo2.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.waitforme.clouddemo2.client.CloudDemo1Client;
import com.waitforme.clouddemo2.service.CloudDemo2Service;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor//为必要的类成员变量生成构造函数
public class CloudDemo2ServiceImpl implements CloudDemo2Service {
  private final CloudDemo1Client client;

  @Override
  public List<Object> getDemo1List() {
    List<Object> list = client.demo1List();
    if (CollUtil.isEmpty(list)) {
      return null;
    }
    return list;
  }
}

对比修改前后的代码:

修改前,使用restTemplate:

修改后:

5.启动测试

 启动服务,并清空IDEA控制台

在浏览器访问cloudDemo2的getDemo1路径,并刷新看我们的控制台输出

刷新三次页面控制台对比,得出可以使用OpenFeign正常调用,使用的是轮询负载均衡策略

cloudDmoe1的服务实例1

 cloudDmoe1的服务实例2

连接池的使用

OpenFeign 使用连接池主要有以下几方面好处:

  1. 性能提升
    • 减少连接创建开销:在频繁发起 HTTP 请求的场景下,如果不使用连接池,每次请求都需要创建新的 TCP 连接。这个创建过程涉及 TCP 三次握手,会消耗额外的网络往返时间以及系统资源。而连接池能够复用已有的连接,避免了反复创建和销毁连接的开销,显著加快请求响应速度。
    • 并发处理更高效:面对高并发的请求,连接池预先创建并管理了一批连接,多个线程可以同时从池中获取连接发起请求,无需等待新连接的缓慢建立,使得系统能够更从容地应对突发流量,提升整体并发处理能力。
  2. 资源优化
    • 降低系统资源消耗:持续不断地创建新连接会占用大量的系统资源,包括内存、CPU 时间等。连接池通过复用有限数量的连接,将资源消耗维持在一个较低水平,尤其对于资源受限的容器化环境或者小型服务器,这有助于维持系统稳定运行,避免因资源耗尽而出现性能瓶颈甚至崩溃。
  3. 稳定性增强
    • 应对网络波动:网络环境往往存在不稳定因素,如短暂的网络抖动、临时的服务中断。连接池中的连接一旦建立,只要没有出现严重故障,就可以持续复用。当遇到轻微网络波动时,不用频繁重新建立连接,减少因网络异常导致请求失败的概率,增强服务调用的稳定性。
  4. 可配置性与管控
    • 灵活配置:连接池通常提供了丰富的配置参数,例如连接池的最大连接数、最小连接数、连接的空闲时长等。开发人员可以根据实际业务场景和服务器资源状况,精细调整这些参数,实现性能与资源消耗之间的最优平衡。
    • 监控与维护:借助连接池,还能够方便地对连接的使用状态进行监控,了解连接的活跃数量、空闲数量、等待获取连接的线程数等关键信息,以便及时发现潜在问题,并采取诸如清理空闲连接、动态调整连接池大小等维护措施。

 1.引入依赖

在cloudDemo2中引入:

<!--OK http 的依赖 -->
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
</dependency>

2.开启连接池

修改cloudDemo2的yaml配置文件,添加:

feign:
  okhttp:
    enabled: true # 开启OKHttp功能

 OpenFeign进阶使用

思考:如果我们的cloudDemo3模块也要调用cloudDemo1的demo1List方法,也要在cloudDemo3上面写一个OpenFeign客户端吗?

所以我们可以把要与其他微服务进行交互的部分抽取出来,单独提成一个微服务来专门管理远程调用

1.抽取Feign客户端

创建一个远程调用的模块

在openFeignApi的pom.xml中导入依赖,并删除cloudDemo2中的如下两个依赖,因为我们已经把远程连接相关的都提到单独的微服务中了,cloudDemo2中也不需要这两个依赖了。

<dependencies>
        <!--open feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- load balancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>

 2.把cloudDemo2中的client包剪切到openFeignApi模块下

3.在cloudDemo2和cloudDemo3的pom.xml中引入openFeign-Api的依赖

<dependency>
    <groupId>com.waitforme</groupId>
    <artifactId>openFeign-Api</artifactId>
    <version>1.0</version>
</dependency>

4.启动测试

 报错?

原因分析:我们把cloudDemo2的feign客户端抽取到了一个独立的微服务中,所以找不到了

解决方案:

1.在cloudDemo2的启动类的EnableFeignClients上声明扫描的包

2.声明要用的FeignClient

最后在浏览器中分别用cloudDemo2和cloudDemo3来访问测试

 日志配置

因为我们把openFeign单独抽出来做了一个微服务,而OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。它的日志级别有:

  • NONE:不记录任何日志信息,这是默认值。

  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

1.定义日志级别

在openFeign-Api下创建一个config包,并创建一个配置类

package com.waitforme.openFeignApi.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;

public class DefaultFeignConfig {
  @Bean
  public Logger.Level feignLogLevel() {
    return Logger.Level.FULL;
  }
}

2.配置

让日志级别生效

方式1:

局部配置,在某个FeignClient上加上configuration属性

@FeignClient(value = "cloudDemo1", configuration = DefaultFeignConfig.class) //cloudDemo1微服务模块中配置文件所配置的微服务名

方式2:

全局配置,在启动类添加defaultConfiguration属性,使FeignClient生效

@EnableFeignClients(clients = {CloudDemo1Client.class}, defaultConfiguration = DefaultFeignConfig.class)

3.重启服务,刷新浏览器请求,测试

控制台日志输出格式:

11:16:15:063 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] ---> GET http://cloudDemo1/cloudDemo1/list HTTP/1.1
11:16:15:065 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] ---> END HTTP (0-byte body)
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] <--- HTTP/1.1 200  (176ms)
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] connection: keep-alive
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] content-type: application/json
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] date: Sun, 29 Dec 2024 03:16:15 GMT
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] keep-alive: timeout=60
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] transfer-encoding: chunked
11:16:15:242 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] 
11:16:15:243 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] ["你好","你好,nacos","你好,微服务"]
11:16:15:243 DEBUG 2456 --- [nio-8082-exec-2] c.w.o.client.CloudDemo1Client            : [CloudDemo1Client#demo1List] <--- END HTTP (48-byte body)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值