Springcloud OpenFeign 详解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Springcloud OpenFeign 详解

 一、概述

OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,整合了hystrix,同时,可以和Eureka和ribbon配合使用,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

官网:Spring Cloud OpenFeign

OpenFegin中的两个常用注解

@FeignClient: 用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入。

@FeignClient标签的常用属性如下:

    • name/value:指定的是调用服务的微服务名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
      • contextId:指定beanID
        • url: url指定调用服务的全路径,一般用于调试,可以手动指定@FeignClient调用的地址
          • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
            • configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
              • fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
                • fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
                  • path: 定义当前FeignClient的统一前缀

                  @EnableFeignClients: Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。

                  二、Feign和openFeign有什么区别?

                  Feign

                  openFiegn

                  Feign是SpringCloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务

                  OpenFeign是SpringCloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

                  三、代码实现:

                  1、POM文件引入依赖:

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

                  image.gif

                  2、添加注解@EnableFeignClients开启openFeign功能

                  @SpringBootApplication
                  @EnableFeignClients
                  public class Application {
                      public static void main(String[] args) {
                          SpringApplication.run(Application.class, args);
                      }
                  }

                  image.gif

                  3、 新建openFeign接口

                  新建一个openFeign接口,使用@FeignClient注解标注,如下

                  @FeignClient("stores")
                  public interface StoreClient {
                      @RequestMapping(method = RequestMethod.GET, value = "/stores")
                      List<Store> getStores();
                      @RequestMapping(method = RequestMethod.GET, value = "/stores")
                      Page<Store> getStores(Pageable pageable);
                      @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
                      Store update(@PathVariable("storeId") Long storeId, Store store);
                      @RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
                      void delete(@PathVariable Long storeId);
                  }

                  image.gif

                  3、openFeign如何传参

                  1. 传递JSON数据

                  如果是 POST 请求,而且是对象集合等参数,在Spring Boot 中通过@RequestBody标识入参

                  @PostMapping("createOrder")
                  public String createOrder(@RequestBody Order order ){
                      System.out.println(order);
                      return "ok";
                  }

                  image.gif

                  2. POJO表单传参

                  Spring Cloud OpenFeign 提供了一个等效的注释,它 用于将 POJO 或 Map 参数注释为查询参数映射。@SpringQueryMap

                  Order createOrder(@SpringQueryMap Order order);

                  下图是官方给出的实例

                  // Params.java
                  public class Params {
                      private String param1;
                      private String param2;
                      // [Getters and setters omitted for brevity]
                  }

                  image.gif

                  以下假装客户端通过注释使用该类:Params@SpringQueryMap

                  @FeignClient("demo")
                  public interface DemoTemplate {
                      @GetMapping(path = "/demo")
                      String demoEndpoint(@SpringQueryMap Params params);
                  }

                  image.gif

                  3.URL中携带参数

                  通过 URL 传参数,GET 请求,参数列表使用@PathVariable(“”)

                  服务提供者代码如下:

                  @RestController
                  @RequestMapping("/openfeign/orderprovider")
                  public class OpenFeignOrderProviderController {
                      @GetMapping("/getOrder/{id}")
                      public String getOrder(@PathVariable("id")Integer id){
                          return "accept one msg id="+id;
                  }

                  image.gif

                  consumer消费者openFeign接口如下:

                  @FeignClient(value = "openFeign-orderprovider")
                  public interface OpenFeignService {
                      @GetMapping("/openfeign/orderprovider/getOrder/{id}")
                      String getOrder(@PathVariable("id")Integer id);
                  }

                  image.gif

                  4、超时如何处理

                  ReadTimeout: 值的是建立链接所用的时间,适用于网络状况正常的情况下, 两端链接所用的时间

                  ConectTimeout: 指的是建立链接后从服务器读取可用资源所用的时间

                  openFeign设置超时时间非常简单,只需要在配置文件中配置,如下:

                  feign:
                    client:
                      config:
                        ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
                        default:
                          connectTimeout: 1000
                          readTimeout: 1000

                  image.gif

                  5、Feign logging

                  为每个创建的 Feign 客户端创建一个记录器。默认情况下,记录器的名称是用于创建 Feign 客户端的接口的完整类名。日志记录仅响应级别:DEBUG。

                  openFeign的日志级别如下:

                  NONE:默认的,不显示任何日志;

                  BASIC:仅记录请求方法、URL、响应状态码及执行时间;

                  HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;

                  FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。

                  配置方式:

                  1. 配置文件application.yml:

                  logging.level.project.user.UserClient: DEBUG

                  image.gif

                  2.自定义一个配置类,在其中设置日志级别

                  @Configuration
                  public class FooConfiguration {
                      @Bean
                      Logger.Level feignLoggerLevel() {
                          return Logger.Level.FULL;
                      }
                  }

                  image.gif

                  6、对@RefreshScope支持

                  如果启用了 Feign 客户端刷新,则使用以下命令创建每个 Feign 客户端:

                    • feign.Request.Options作为刷新范围的 Bean。这意味着像connectTimeout and readTimeout 等属性可以针对任何 Feign 客户端实例刷新。
                      • 在 下换行的网址org.springframework.cloud.openfeign.RefreshableUrl。这意味着 Feign 客户端的 URL(如果已定义)spring.cloud.openfeign.client.config.{feignName}.url 属性,可以针对任何 Feign 客户端实例刷新。

                      可以通过 刷新这些属性。POST /actuator/refresh

                      默认情况下,Feign 客户端中的刷新行为处于禁用状态。使用以下属性启用刷新行为:

                      spring.cloud.openfeign.client.refresh-enabled=true

                      image.gif

                      7、假请求/响应压缩

                      您可以考虑为您的启用请求或响应 GZIP 压缩 佯装请求。您可以通过启用以下属性之一来执行此操作:

                      spring.cloud.openfeign.compression.request.enabled=true
                      spring.cloud.openfeign.compression.response.enabled=true

                      image.gif

                      假请求压缩为您提供的设置类似于您可能为 Web 服务器设置的设置:

                      spring.cloud.openfeign.compression.request.enabled=true
                      spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json
                      spring.cloud.openfeign.compression.request.min-request-size=2048

                      image.gif

                      这些属性允许您选择压缩媒体类型和最小请求阈值长度。

                      8、Feign Spring Cloud CircuitBreaker Fallbacks

                      Spring Cloud CircuitBreaker支持回退的概念:当链路断开或出现错误时执行的默认代码路径。要为给定的@FeignClient启用回退,请将回退属性设置为实现回退的类名。您还需要将您的实现声明为Springbean:

                      @FeignClient(name = "test", url = "http://localhost:${server.port}/", fallback = Fallback.class)
                          protected interface TestClient {
                              @RequestMapping(method = RequestMethod.GET, value = "/hello")
                              Hello getHello();
                              @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
                              String getException();
                          }
                          @Component
                          static class Fallback implements TestClient {
                              @Override
                              public Hello getHello() {
                                  throw new NoFallbackAvailableException("Boom!", new RuntimeException());
                              }
                              @Override
                              public String getException() {
                                  return "Fixed response";
                              }
                          }

                      image.gif

                      如果需要访问导致回退触发的原因,可以在@FeignClient中使用fallbackFactory属性:

                      @FeignClient(name = "testClientWithFactory", url = "http://localhost:${server.port}/",
                                  fallbackFactory = TestFallbackFactory.class)
                          protected interface TestClientWithFactory {
                              @RequestMapping(method = RequestMethod.GET, value = "/hello")
                              Hello getHello();
                              @RequestMapping(method = RequestMethod.GET, value = "/hellonotfound")
                              String getException();
                          }
                          @Component
                          static class TestFallbackFactory implements FallbackFactory<FallbackWithFactory> {
                              @Override
                              public FallbackWithFactory create(Throwable cause) {
                                  return new FallbackWithFactory();
                              }
                          }
                          static class FallbackWithFactory implements TestClientWithFactory {
                              @Override
                              public Hello getHello() {
                                  throw new NoFallbackAvailableException("Boom!", new RuntimeException());
                              }
                              @Override
                              public String getException() {
                                  return "Fixed response";
                              }
                          }

                      image.gif

                      9、Feign and @Primary

                      当将Feign与Spring Cloud CircuitBreaker回退一起使用时,ApplicationContext中存在多个相同类型的bean。这将导致@Autowired无法工作,因为没有确切的一个bean,或者一个被标记为primary。为了解决这个问题,Spring Cloud OpenFeign将所有Feign实例标记为@Primary,这样Spring Framework就会知道要注入哪个bean。在某些情况下,这可能是不可取的。若要关闭此行为,请将@FeignClient的主属性设置为false:

                      @FeignClient(name = "hello", primary = false)
                      public interface HelloClient {
                          // methods here
                      }

                      image.gif

                      10、Feign Caching

                      如果使用@EnableCaching annotation,则会创建并注册CachingCapability bean,以便您的Feign客户端在其接口上识别@Cache*annotations:

                      public interface DemoClient {
                          @GetMapping("/demo/{filterParam}")
                          @Cacheable(cacheNames = "demo-cache", key = "#keyParam")
                          String demoEndpoint(String keyParam, @PathVariable String filterParam);
                      }

                      image.gif

                      您也可以通过属性spring.cloud.openfacy.cache.enabled=false禁用该功能。




                      Doker 技术人的数码品牌!!!

                      文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群!!!

                      你的支持和鼓励是我创作的动力❗❗❗

                      官网:Doker 多克; 官方旗舰店首页-Doker 多克官方旗舰店 全品8.5折优惠,购前请和店小二说明来自阿里云!!!

                      相关实践学习
                      日志服务之使用Nginx模式采集日志
                      本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
                      DOKER
                      +关注
                      目录
                      打赏
                      0
                      1
                      1
                      0
                      791
                      分享
                      相关文章
                      Spring Cloud Alibaba与Spring Cloud区别和联系?
                      Spring Cloud Alibaba与Spring Cloud区别和联系?
                      🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
                      本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
                      107 0
                      🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
                      AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
                      本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
                      262 4
                      深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
                      深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
                      249 5
                      【Spring Cloud生态】Spring Cloud Gateway基本配置
                      【Spring Cloud生态】Spring Cloud Gateway基本配置
                      106 0
                      【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
                      【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
                      180 1
                      【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
                      【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
                      【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
                      【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
                      【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
                      【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
                      【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
                      【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
                      AI助理

                      你好,我是AI助理

                      可以解答问题、推荐解决方案等