feign的Fallback机制

2023-11-20

对接口使用@FeignClient后声明feign客户端后,可以使用属性fallback指定异常处理类,这个类必须实现@FeignClient作用的接口,且被注入到容器中。

@FeignClient(name = "service-provider1",fallback = NacosFeignImpl.class)
public interface NacosFeignClient {
    @RequestMapping(value = "/echo/{str}",method = RequestMethod.GET)
    String echo(@PathVariable("str") String str);
}
@Component
public class NacosFeignImpl implements NacosFeignClient{
    @Override
    public String echo(String str) {
        System.out.println("NacosFeignImpl#echo called");
        return "echo error";
    }
}

添加配置项feign.hystrix.enabled=true,当配置了HystrixFeign时,即会创建HystrixFeign.Builder。

// FeignClientsConfiguration.java
	@Configuration
	@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
	protected static class HystrixFeignConfiguration {
		@Bean
		@Scope("prototype")
		@ConditionalOnMissingBean
		@ConditionalOnProperty(name = "feign.hystrix.enabled")
		public Feign.Builder feignHystrixBuilder() {
			return HystrixFeign.builder();
		}
	}

在HystrixTargeter#target()发现使用了HystrixFeign.Builder并且属性fallback存在时,就会通过targetWithFallback()创建feign客户端。这里会到容器中获取实现了@FeignClient接口的Bean。

	public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
						Target.HardCodedTarget<T> target) {
		if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
			return feign.target(target);
		}
		feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
		SetterFactory setterFactory = getOptional(factory.getName(), context,
			SetterFactory.class);
		if (setterFactory != null) {
			builder.setterFactory(setterFactory);
		}
		Class<?> fallback = factory.getFallback();
		if (fallback != void.class) {
			return targetWithFallback(factory.getName(), context, target, builder, fallback);
		}
		Class<?> fallbackFactory = factory.getFallbackFactory();
		if (fallbackFactory != void.class) {
			return targetWithFallbackFactory(factory.getName(), context, target, builder, fallbackFactory);
		}

		return feign.target(target);
	}

此时创建InvocationHandlerFactory,注入到属性invocationHandlerFactory,invocationHandlerFactory默认是InvocationHandlerFactory.Default,这里重写create()方法,创建了HystrixInvocationHandler的实例对象。

    Feign build(final FallbackFactory<?> nullableFallbackFactory) {
      super.invocationHandlerFactory(new InvocationHandlerFactory() {
        @Override public InvocationHandler create(Target target,
            Map<Method, MethodHandler> dispatch) {
          return new HystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory);
        }
      });
      super.contract(new HystrixDelegatingContract(contract));
      return super.build();
    }

生成代理对象时,就会调用create()对HystrixInvocationHandler实例化,这样就会调用HystrixInvocationHandler#invoke()。

  public <T> T newInstance(Target<T> target) {
    ......
    InvocationHandler handler = factory.create(target, methodToHandler);
    T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);

    for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
      defaultMethodHandler.bindTo(proxy);
    }
    return proxy;
  }

invoke()中run()的逻辑还是调用SynchronousMethodHandler#invoke()处理请求,发生异常时就会到getFallback()调用接口的实现类对象的方法。

  public Object invoke(final Object proxy, final Method method, final Object[] args)
      throws Throwable {
    // early exit if the invoked method is from java.lang.Object
    // code is the same as ReflectiveFeign.FeignInvocationHandler
    if ("equals".equals(method.getName())) {
      try {
        Object otherHandler =
            args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
        return equals(otherHandler);
      } catch (IllegalArgumentException e) {
        return false;
      }
    } else if ("hashCode".equals(method.getName())) {
      return hashCode();
    } else if ("toString".equals(method.getName())) {
      return toString();
    }

    HystrixCommand<Object> hystrixCommand = new HystrixCommand<Object>(setterMethodMap.get(method)) {
      @Override
      protected Object run() throws Exception {
        try {
          return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
        } catch (Exception e) {
          throw e;
        } catch (Throwable t) {
          throw (Error) t;
        }
      }

      @Override
      protected Object getFallback() {
        if (fallbackFactory == null) {
          return super.getFallback();
        }
        try {
          Object fallback = fallbackFactory.create(getExecutionException());
          Object result = fallbackMethodMap.get(method).invoke(fallback, args);
          if (isReturnsHystrixCommand(method)) {
            return ((HystrixCommand) result).execute();
          } else if (isReturnsObservable(method)) {
            // Create a cold Observable
            return ((Observable) result).toBlocking().first();
          } else if (isReturnsSingle(method)) {
            // Create a cold Observable as a Single
            return ((Single) result).toObservable().toBlocking().first();
          } else if (isReturnsCompletable(method)) {
            ((Completable) result).await();
            return null;
          } else {
            return result;
          }
        } catch (IllegalAccessException e) {
          // shouldn't happen as method is public due to being an interface
          throw new AssertionError(e);
        } catch (InvocationTargetException e) {
          // Exceptions on fallback are tossed by Hystrix
          throw new AssertionError(e.getCause());
        }
      }
    };

    if (isReturnsHystrixCommand(method)) {
      return hystrixCommand;
    } else if (isReturnsObservable(method)) {
      // Create a cold Observable
      return hystrixCommand.toObservable();
    } else if (isReturnsSingle(method)) {
      // Create a cold Observable as a Single
      return hystrixCommand.toObservable().toSingle();
    } else if (isReturnsCompletable(method)) {
      return hystrixCommand.toObservable().toCompletable();
    }
    return hystrixCommand.execute();
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

feign的Fallback机制 的相关文章

  • 如何让Spring RabbitMQ创建一个新的队列?

    根据我对rabbit mq的 有限 经验 如果您为尚不存在的队列创建新的侦听器 则会自动创建该队列 我正在尝试将 Spring AMQP 项目与rabbit mq 一起使用来设置侦听器 但出现错误 这是我的 xml 配置
  • JavaFX Platform.runLater 的使用以及从不同线程访问 UI

    我有几个问题Platform runLater 我有一个 JavaFX 应用程序类 在这个类中 我运行一个线程 该线程从网络套接字读取数据 现在当我创建一个新的Stage在线程内部 系统抛出异常 JavaFX 事件调度程序线程和我的网络读取
  • Java:高性能消息传递(单生产者/单消费者)

    我最初问这个问题here https stackoverflow com questions 3367192 java is while true loop in a thread bad whats the alternative 但我意
  • 实现与扩展:何时使用?有什么不同?

    请用易于理解的语言进行解释或提供某些文章的链接 extends is for 延伸一类 implements is for 实施一个接口 接口和常规类之间的区别在于 在接口中您不能实现任何声明的方法 只有 实现 接口的类才能实现方法 C 中
  • 线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有opencv_java249

    我目前正在尝试在我的 32 位笔记本电脑上设置 OpenCV 但我不断收到一条令我困惑的错误消息 Exception in thread main java lang UnsatisfiedLinkError no opencv java2
  • 无法实例化接收器 com.parse.GcmBroadcastReceiver

    我正在编写一个使用 GCM 通知和解析推送的离子应用程序 这个应用程序正在使用这些插件 com ionic keyboard 1 0 3 Keyboard com phonegap plugins PushPlugin 2 4 0 Push
  • 如何修复 Android 7.0 的 Spinner 模式下的 DatePickerDialog?

    我目前正在开发一个简单的项目 其中包含一个包含在 Web 视图中的网站 具有少量交互 以提高网站本身和 Android 移动设备之间的交互性 由于该网站包含用户生日的日期输入字段 因此我希望实现一个与所有设备兼容的旋转格式的日期选择器 我尝
  • Java 唤醒休眠线程

    我阅读了其他帖子 但没有找到我正在寻找的确切答案 所以我希望有人能给出一些澄清 我有一个将运行一段时间的程序 我有一些在后台运行的线程来执行各种任务 为了简单起见 让我们考虑 3 个线程 ThreadA每 10 秒执行一次任务 其中Thre
  • 支持通过 OAuth 进行 Facebook/Twitter 身份验证的 CAS 服务器

    我正在寻找一个支持 Facebook Twitter 通过 OAuth 进行单点登录身份验证的 CAS 服务器 我检查过 JASIG CAS 服务器 但它看起来不支持它们 我的 java web 应用程序基于 Spring Security
  • Java:使用 Java.util.concurrent 线程访问读取线程串行端口

    我正在尝试编写一个 Java 串行设备驱动程序并想使用 对我来说是新的 java util concurrent包裹 我有一种发送数据包然后等待 ACK 的方法 我打算有炭 接收在不同的线程中运行 如果接收线程收到 ACK 它应该使用发送数
  • 使用Java开发跨平台,不同平台字体缩放不同

    我正在为我的大学制作一些软件 需要一个 GUI 在它的第一个版本中 我让它使用系统外观 因此它看起来像 Linux Mac Windows 中的本机应用程序 我发现这很麻烦 因为我必须根据操作系统使所有 JLabel 具有不同的大小 无论分
  • 为什么现在()? (客观化)

    为什么我想要异步加载 Objectify 实体 异步加载到底意味着什么 根据客观化有关加载的文档 https code google com p objectify appengine wiki BasicOperations Loadin
  • 在Java中多次读取System.in会导致IOException?

    我正在尝试创建一个小命令行游戏来强化我在过去几个月中在 Java 中学到的一些东西 我正在尝试创建一个名为 readInput 的方法 它返回一个我可以一次又一次调用的字符串 第一次它工作正常 但第二次它会导致 IO Exception 如
  • 战争库中的罐子爆炸

    我们可以将分解的 jar 文件放入 war web inf 库中吗 它在 JBOSS 4 2 中对我不起作用 我收到以下错误并且无法部署应用程序 Caused by javax management RuntimeOperationsExc
  • 我们可以有虚假中断吗?

    我正在创建一个任务轮询器 每分钟都会查找任务 它看起来像这样 public class Poller private final ExecutorService e Executors newSingleThreadExecutor pub
  • 无法映射 ftl 文件中的 jsonRequest 属性

    我想在 FTL 文件中映射下面的 json 文件市场和子市场字段 但是当我尝试下面的代码时 它没有映射 有人可以帮助我吗 我从 2 天开始就无法映射它 Json请求 ProcessOrderRequest prevalidationMode
  • 找不到符号assertEquals

    我正在尝试为计算器编写第一个单元测试 但 NetBeans 说它找不到该符号assertEquals和注释 Test 我应该包括一些东西吗 我正在使用 NetBeans 7 3 1 和 W7 package calculator impor
  • 从命令行运行 Maven 插件的语法是什么。

    我看到这里已经有人问过这个问题 如何从命令行执行maven插件 https stackoverflow com questions 12930656 how to execute maven plugin from command line
  • 将带有 webapp 的 WAR 部署到 Maven 中央存储库是否有意义?

    这样做有意义吗 如果是 我在哪里可以找到使用简单的 Web Hello World 执行此操作的示例 当人们从 Maven 执行 Web 应用程序时 他们会使用 Jetty 来运行它吗 我想 tomcat 太重了 任何帮助将不胜感激 谢谢
  • H2 用户定义的聚合函数 ListAgg 不能在第一个参数上使用 DISTINCT 或 TRIM()

    所以我有一个 DB2 生产数据库 我需要在其中使用可用的函数 ListAgg 我希望使用 H2 的单元测试能够正确测试此功能 不幸的是H2不直接支持ListAgg 但是 我可以创建一个用户定义的聚合函数 import java sql Co

随机推荐

  • 看懂2020年智能浪潮,我们从百度和谷歌的AI足迹出发

    2020年已经过去 无论我们过得顺遂平安 还是过得无比艰难 我们应该都会记住这一年 回顾2020年 在这个不同寻常的疫情之年 科技成为人类抗击疫情的关键 而人工智能技术投入抗疫战争之中 可以说是人类有史以来的第一次 而与此同时 AI技术已经
  • [Note ]B站翼王10TB和100TB FreeNas硬件笔记以及配置

    BV18W411f7u9 DIY一台高性能的MINI ITX文件服务器 还要能使用万兆网络 BV1qE411672a 年轻人的第一台自己组装的100TB 容量的文件服务器 准备自己在家里搭Nas 家里人的手机存储也经常不够 自己也对硬件特别
  • SCSI、ISCSI、iSER、NVMe、NVMe-oF、NVMe-oF over RDMA

    在存储系统中 上层协议可以泛指 指令 也就是比如 读出从某某开始的多少长度的扇区 指令包含三大关键信息 1 操作码 Opreation Code 或称为OP code 比如write read等等 2 起始地址 从哪里开始读 如果是文件的话
  • 利用Redis实现分布式全局唯一ID

    Component public class RedisIdWorker 开始时间戳 private static final long BEGIN TIMESTAMP 1640995200L 序列号的位数 private static f
  • windows或者任何系统通过二进制安装最新的Protocol Buffer Compiler

    此处使用二进制法安装 适用于任何操作系统 安装预编译的二进制文件 任何操作系统 要从预编译的二进制文件安装最新版本的协议编译器 请按照以下说明操作 1 从 github com google protobuf releases 手动下载与您
  • 组合型模式

    概述 对于这个图片肯定会非常熟悉 上图我们可以看做是一个文件系统 对于这样的结构我们称之为树形结构 在树形结构中可以通过调用某个方法来遍历整个树 当我们找到某个叶子节点后 就可以对叶子节点进行相关的操作 可以将这颗树理解成一个大的容器 容器
  • Python 房价预测 kaggle 线性回归 SVM 神经网络 随机森林 集成模型

    摘要 现如今房产成为大多数家庭总资产中占比最大的一部分 也成为国人投资的重要渠道 研究和预测房产价格对我国人民和宏观经济发展都有重要价值 本文对包含房产各项基本信息及价格的数据进行处理 利用包括线性回归 核岭回归 支持向量回归 神经网络 决
  • C、C++ 中\n、\t、\r的具体用法功能

    简单介绍 n 表示换行操作 光标会移动到下一行 next line t 表示水平制表空行操作 相当于Tab键 不会换行 r 相当于回车 相当于光标回到本行首位置 不会换行 用法实例演示 我们以一个9x9乘法表C 具体代码为例 演示一个三个的
  • 使用七牛云进行文件上传

    目录 一 七牛云入门测试 1 注册七牛云账号 完成后选择对象存储 2 在里面创建空间 一个空间相当于一个文件夹 就是将对象上传到的地方 3 查看个人秘钥 注册完成账号后 会有一个秘钥 上传文件的时候进行授权和认证 4 文件上传测试 二 封装
  • 汇编程序设计与计算机体系结构软件工程师教程笔记:汇编语法基础知识

    汇编程序设计与计算机体系结构 软件工程师教程 这本书是由Brain R Hall和Kevin J Slonka著 由爱飞翔译 中文版是2019年出版的 个人感觉这本书真不错 书中介绍了三种汇编器GAS NASM MASM异同 全部示例代码都
  • 2021.10.04 task9 react-hardhat

    2021 10 04 主要根据dapp learning的教程在学习 在学习task 9 hardhat react 的部分 区块链项目大部分用的都是 react 所以了解 react的基本机制也很重要 今天着重学习了react react
  • 测试报告和结果分析 —— allure整合pytest生成测试报告

    一 生成HTML测试报告的三种方式 1 unittest和HTMLTestRunner整合 2 allure和pytest整合 3 Jenkins中安装allure插件 Jenkins安装插件出错 不能正常使用 二 allure整合pyte
  • 知识图谱:语义网络、语义网、链接数据、知识图谱

    0 发展历程 1 语义网络 Semantic Networks 语义网络是由Quillian于上世纪60年代提出的知识表达模式 其用相互连接的节点和边来表示知识 节点表示对象 概念 边表示节点之间的关系 语义网络的优点 1 容易理解和展示
  • ubuntu系统中jupyterhub安装R内核集成rstudio

    需求 最后公司需要将原来用的Jupyter单用户版本改成Jupyterhub多用户版本 方便公司统一管理用户 并且因为平时工作会用到python和R的IDE 正好Jupyterhub可以满足需求 网上搜了很多 基本是三种方式 一种是通过k8
  • 公司后台管理系统搭建(Vue3+Vite+Element Plus+TypeScript+Pinia)

    前言 此次项目搭建选用 Vue3 Vite 并使用 pnpm 管理依赖包 本文将从下载到项目创建记录项目全过程 一 项目搭建 1 使用 npm 下载 pnpm 使用 pnpm 依赖包将被存放在一个统一的位置 因此可以节省大量的硬盘空间以及提
  • 自定义ViewGroup实现流式布局

    目录 1 View的绘制流程 2 自定义ViewGroup构造函数的作用 3 onMeasure 方法 3 1 View的度量方式 3 2 onMeasure方法参数的介绍 3 3 自定义ViewGroup onMeasure 方法的实现
  • HiveSQL原理和优化详解

    Hive SQL 编译成MapReduce过程 编译 SQL 的任务是在上节中介绍的 COMPILER 编译器组件 中完成的 Hive将SQL转化为MapReduce任务 整个编译过程分为六个阶段 词法 语法解析 Antlr 定义 SQL
  • javascript相关

    1 扁平数据结构转Tree 打平的数据内容如下 let arr id 1 name 部门1 pid 0 id 2 name 部门2 pid 1 id 3 name 部门3 pid 1 id 4 name 部门4 pid 3 id 5 nam
  • vscode编辑器插件总结

    之前一直用webstorm webstorm确实太重了 后来无意中发现了vscode 高颜值吸引了我哈哈哈 就一直用着 很喜欢VScode的插件功能 想要什么插件就搜索 比如搜索angular 只要点击一下某款插件 插件的介绍和用法都会在右
  • feign的Fallback机制

    对接口使用 FeignClient后声明feign客户端后 可以使用属性fallback指定异常处理类 这个类必须实现 FeignClient作用的接口 且被注入到容器中 FeignClient name service provider1