OpenFeign

简介

OpenFeign是基于声明式的REST 客户端,用于简化服务间远程调用。(编程式REST客户端(RestTemplate))

通过接口+注解方式定义HTTP请求,自动实现服务调用

常用注解:

  • 指定远程地址:@FeignClient
  • 指定请求方式:@GetMapping、@PostMapping、@DeleteMapping …
  • 指定携带数据:@RequestHeader、@RequestParam、@RequestBody …
  • 指定返回结果:响应模型

官网:https://docs.spring.io/spring-cloud-openfeign/reference/spring-cloud-openfeign.html#spring-cloud-feign

总结:OpenFeign是一种替代RestTemplate的工具,专门用来实现不同微服务之间实现远程调用的服务API,相比RestTemplate功能更强大,操作更简洁

使用示例

  1. 引入依赖

    <!-- Spring Cloud OpenFeign 核心依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 开启功能

    在主启动类添加注解:

    @EnableFeignClients // 启用 OpenFeign 客户端功能
    @SpringBootApplication
    public class Application { ... }
    
  3. 远程调用

    • 定义Feign客户端接口: (客户端:发送请求,服务端:接收请求)

    • 远程调用--业务API

      @FeignClient(value = "product-service")//声明要调用的Feign客户端,名称是application.yml中配置的名称,底层会自动去注册中心负载均衡的发送请求
      public interface ProductFeignClient {//使用feign实现的专门向product服务进行调用的接口
          //mvc注解的两套逻辑
          //1.标注在Controller上,是接收这一样的请求
          //2.标注在FeignClient上,是发送这样的请求
          @GetMapping("/product/{id}")
          public Product getProductById(@PathVariable("id") Long productId);
      }
      //接收请求的时候是把这个id放到productId
      //发送请求的时候是把productId放到id上
      
    • 远程调用--第三方API

如何编写好OpenFeign声明式的远程调用接口

  • 业务API:直接复制对方Controller签名即可
  • 第三方API:根据接口文档确定请求如何发

注入使用:

@Autowired
private UserClient userClient;
public User getUser(Long id) {
    return userClient.getUserById(id); // 直接调用远程接口
}

面试题: 客户端负载均衡与服务端负载均衡区别?

负载均衡发生在客户端就是客户端负载均衡。

负载均衡发生在服务端就是服务端负载均衡。

进阶配置

开启日志

配置日志级别(application.yml)

# 客户端
logging:
  level:
    com.atguigu.order.Feign: DEBUG # 指定客户端接口的日志级别,直接复制包名,这样其下的所有客户端就都会开启日志功能

配置日志策略(java Config)

@Configuration
//注意一定是feign包下的Logger
import feign.Logger;

//OrderConfig
@Configuration
public class OrderConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL; // FULL/BASIC/HEADERS/NONE
    }
}

超时控制(避免服务宕机)

商品服务卡慢导致订单服务卡慢,导致。。。链式效应进而导致整个服务的卡慢,(服务雪崩)因此我们需要一个超时控制机制。

connectTimeout: 打电话嘟嘟嘟,没人接(电话没接通)

readTimeout: 喂喂喂,没人回(电话接通了)

# application.yml
spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            logger-level: full
            connect-timeout: 1000 # ms
            read-timeout: 2000
          product-service:
            logger-level: full
            connect-timeout: 3000
            read-timeout: 5000

重试机制

远程调用超时失败后,还可以进行多次尝试,如果某次成功返回ok,如 果多次依然失败则结束调用,返回错误。(一次调用失败我不甘心,我想多试几次。)

配置方式一 配置文件方式

# application.yml
spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            retryable: true # 启用重试
            maxAttempts: 3 # 最大重试次数

配置方式二 编码方式

@Bean
Retryer retryer(){
    return new Retryer.Default();
}
//spring会自动把retryer注入到容器,注入之后底层会默认这个配置(源码)
public Default() {
    this(100L, TimeUnit.SECONDS.toMillis(1L), 5);//请求超时默认发5次,最多1s
}

Fallback 兜底返回

  1. 引入sentinel

    <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
     </dependency>
    
  2. 开启熔断

    feign:
      sentinel:
        enabled: true
    
  3. 编写Fallback函数

    @FeignClient(value = "service-product",fallback = ProductFeignClientFallback.class) // feign客户端
    public interface ProductFeignClient {
       //mvc注解的两套使用逻辑
       //1、标注在Controller上,是接收这样的请求
       //2、标注在FeignClient上,是发送这样的请求
       @GetMapping("/product/{id}")
       Product getProductById(@PathVariable("id") Long id);
    }
    
    // Feign包下创建一个FallBack包(兜底回调)
    // FallBack包在创建ProductFeignClientFallback,并且继承ProductFeignClient(接口)
    @Component//只有把这个兜底回调放在容器中才能实现兜底回调
    public class ProductFeignClientFallback implements ProductFeignClient {
    	//这个函数不一定会回调,只有出现超时情况才会调用这个函数
        public Product getProductById(Long id) {
            System.out.println("兜底回调....");
            Product product = new Product();
            product.setId(id);
            product.setPrice(new BigDecimal("0"));
            product.setProductName("未知商品");
            product.setNum(0);
            return product;
        }
    }
    

拦截器用法

  1. 请求拦截器
  2. 响应拦截器(用的不多)

自定义拦截器

import feign.RequestInterceptor;

@Component//如果放入IOC容器就会自动注册拦截器,可以不做后面的注册
public class XTokenRequestInterceptor implements RequestInterceptor {
    /**
    *请求拦截器
    *template 请求模板
    */
    @Override
    public void apply(RequestTemplate template) {
        System.out.println("XTokenRequestInterceptor.......");
        template.header("X-Token", "UUID.randomUUID.toString()"); // 添加请求头,用作身份验证
    }
}

注册拦截器(配置类中):

@Configuration
public class FeignConfig {
    @Bean
    public AuthInterceptor authInterceptor() {
        return new AuthInterceptor();
    }
}

重点总结

核心内容 关键点 备注
远程调用客户端 通过 @FeignClient 定义接口,使用 @GetMapping 等注解声明 HTTP 方法。
超时控制 配置 connectTimeoutreadTimeout,支持全局和按服务配置。
重试机制 启用 retryable 并设置 maxAttempts,增强服务调用容错性。
Fallback 兜底 实现 Fallback 类处理服务降级,防止级联故障。
拦截器 通过 RequestInterceptor 添加统一请求头或认证信息。

注意事项

  1. 生产环境建议配置合理的超时时间和重试策略,避免雪崩效应。
  2. 拦截器可用于统一认证、日志跟踪等场景。

OpenFeign 与 Dubbo 的区别

Dubbo 和 OpenFeign 都是java生态中两个广泛使用的远程过程调用(RPC)框架,两者主要在稳定性、独立性和易用性等方面有所区别,具体如下:

  1. 稳定性
    • Dubbo:基于TCP进行传输,处于更底层的模型,数据传输稳定,特别是处理大量并发请求时表现优秀
    • OpenFeign:基于HTTP协议进行传输,通常为短连接,适合轻量级微服务调用,但在高并发场景下可能不如Dubbo稳定
  2. 独立性
    • Dubbo:是一个独立的RPC框架,提供了完整的服务治理解决方案,不依赖其他系统或者框架
    • OpenFeign:作为Spring Cloud 生态的一部分,与Spring Cloud 集成紧密,简化了服务间的调用,但相对依赖Spring生态系统
  3. 易用性
    • Dubbo:需要较多的配置和代码实现,但能够提供灵活的服务治理能力
    • OpenFeign:使用非常简单,只需要在接口上添加注解即可完成服务的暴露与调用,降低了学习成本和开发成本
  4. 负载均衡
    • Dubbo:支持随机、轮询、活跃度、Hash一致性等多种算法,并引入权重概念,支持动态配置
    • OpenFeign:支持轮询,随机,ResponseTime加权等策略,但相对较为简单
  5. 容错策略
    • Dubbo:支持failover、failfast、broadcast、forking等多种容错策略,并可配置retry次数和timeout参数
    • OpenFeign:利用熔断机制进行容错处理,与Dubbo的处理方式有所不同
  6. 适用场景
    • Dubbo:适用于大型的分布式项目,能够处理复杂的业务逻辑和高并发请求
    • OpenFeign:适合轻量级的微服务架构,业务逻辑相对简单,并且与Spring Cloud技术栈配合使用更佳

综合对比分析,Dubbo更适合大规模、高并发的分布式系统,其强大的服务治理能力和灵活性使其在复杂场景下表现突出。相反,OpenFeign更加适合轻量级微服务架构,其简洁性和与Spring Cloud的集成度使得开发和部署更加便捷。此外,技术栈的熟悉程度和团队经验也是选择的重要考虑因素。

在选择时,提供如下几点建议:

  • 如果当前项目已经基于Spring Cloud构建,推荐使用OpenFeign以减少整合成本。
  • 对于对性能有极高要求或者独立的RPC框架需求的项目,Dubbo将是更好的选择。
  • 考虑到社区活跃度和支持,Dubbo可能提供更多的文档和问题解决途径。
  • 如果计划构建一个全新项目,可以依据具体的业务需求、团队技能和未来的拓展预期来决定使用哪个框架。

综上所述,Dubbo和OpenFeign各有优势,选择合适的框架取决于具体的项目需求和应用场景。在做出决策之前,请仔细评估项目的规模、技术栈和性能要求。无论选择哪个框架,都需要深入理解其工作原理和最佳实践,以便在实际应用中获得最佳的性能和可靠性。

posted @ 2025-09-08 22:28  小郑[努力版]  阅读(13)  评论(0)    收藏  举报