springboot openfeign Sentinel统一降级处理

news2024/11/28 5:51:16

背景

openfeign降级常规操作如下:
在这里插入图片描述
此种方式太过于麻烦,每一个方法都要写一个降级逻辑,并且降级逻辑大多是雷同的。

目标

提供默认的降级方式,若openfeign未指定FallbackFactory则走默认降级方式,否则就走自定义的FallbackFactory降级。文末附实现代码下载

版本

  1. springcloud
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-dependencies</artifactId>
	<version>2021.0.1</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>
  1. sentinel
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
	<version>2021.0.1.0</version>
</dependency>

实现

  • 查看spring-cloud-starter-alibaba-sentinel降级源码
    在这里插入图片描述
    从上述源码可以看到若不存在自定义的fallbackFactory,则直接抛异常,我们需要做的就是在抛异常之前插入我们的默认降级逻辑。这里有如下两种插入代码块方式:
    1:Java ASM字节码修改技术插入,过往文章:https://blog.csdn.net/qq_41633199/article/details/117160642
    2:参照SentinelInvocationHandler源码新建一个java文件手动写入代码块,再替换sentinel的默认实现
    这里我选择方法2.
  • 添加默认降级逻辑
    • 参照SentinelInvocationHandler.java源码新建一个java文件DegradeSentinelInvocationHandler.java
    • 手动写入默认降级方法
if (fallbackFactory != null) {
	try {
		Object fallbackResult = fallbackMethodMap.get(method)
			.invoke(fallbackFactory.create(ex), args);
		return fallbackResult;
	}
	catch (IllegalAccessException e) {
		// shouldn't happen as method is public due to being an
		// interface
		throw new AssertionError(e);
	}
	catch (InvocationTargetException e) {
		throw new AssertionError(e.getCause());
	}
}
else {
	//没有自定义降级处理,并且返回格式是R,则进行统一降级处理
	if (method.getReturnType().equals(R.class)) {
		log.warn(ex.getMessage(), ex);
		String failMsg = ofNullable(ex).map(Throwable::getMessage).filter(CharSequenceUtil::isNotEmpty).orElse("系统异常,请联系管理员");
		return R.error(failMsg);
	}
	throw ex;
}
  • 参照com.alibaba.cloud.sentinel.feign.SentinelFeign.java新建DegradeSentinelFeign.java构建Feign对象
    核心代码:
@Override
public Feign build() {
	super.invocationHandlerFactory(new InvocationHandlerFactory() {
		@Override
		public InvocationHandler create(Target target,
										Map<Method, MethodHandler> dispatch) {
			GenericApplicationContext gctx = (GenericApplicationContext) DegradeSentinelFeign.Builder.this.applicationContext;
			BeanDefinition def = gctx.getBeanDefinition(target.type().getName());

			/*
			 * Due to the change of the initialization sequence,
			 * BeanFactory.getBean will cause a circular dependency. So
			 * FeignClientFactoryBean can only be obtained from BeanDefinition
			 */
			FeignClientFactoryBean feignClientFactoryBean = (FeignClientFactoryBean) def
				.getAttribute("feignClientsRegistrarFactoryBean");

			Class fallback = feignClientFactoryBean.getFallback();
			Class fallbackFactory = feignClientFactoryBean.getFallbackFactory();
			String beanName = feignClientFactoryBean.getContextId();
			if (!StringUtils.hasText(beanName)) {
				beanName = (String) getFieldValue(feignClientFactoryBean, "name");
			}

			Object fallbackInstance;
			FallbackFactory fallbackFactoryInstance;
			// check fallback and fallbackFactory properties
			if (void.class != fallback) {
				fallbackInstance = getFromContext(beanName, "fallback", fallback,
					target.type());
				return new DegradeSentinelInvocationHandler(target, dispatch,
					new FallbackFactory.Default(fallbackInstance));
			}
			if (void.class != fallbackFactory) {
				fallbackFactoryInstance = (FallbackFactory) getFromContext(
					beanName, "fallbackFactory", fallbackFactory,
					FallbackFactory.class);
				return new DegradeSentinelInvocationHandler(target, dispatch,
					fallbackFactoryInstance);
			}

			return new DegradeSentinelInvocationHandler(target, dispatch);
		}

		private Object getFromContext(String name, String type,
									  Class fallbackType, Class targetType) {
			Object fallbackInstance = feignContext.getInstance(name,
				fallbackType);
			if (fallbackInstance == null) {
				throw new IllegalStateException(String.format(
					"No %s instance of type %s found for feign client %s",
					type, fallbackType, name));
			}

			if (!targetType.isAssignableFrom(fallbackType)) {
				throw new IllegalStateException(String.format(
					"Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
					type, fallbackType, targetType, name));
			}
			return fallbackInstance;
		}
	});

	super.contract(new SentinelContractHolder(contract));
	return super.build();
}
  • 参照com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration.java新建DegradeSentinelFeignAutoConfiguration.java替换Sentinel自带降级处理逻辑
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SphU.class, Feign.class, SentinelFeignAutoConfiguration.class})
@AutoConfigureBefore(SentinelFeignAutoConfiguration.class)
public class DegradeSentinelFeignAutoConfiguration {

    @Bean
    @Scope("prototype")
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "feign.sentinel.enabled")
    public Feign.Builder feignSentinelBuilder() {
        return DegradeSentinelFeign.builder();
    }
}
  • 在spring.factories文件指定自定义降级配置类
    在这里插入图片描述

完整代码下载

springboot openfeign Sentinel统一降级处理实现代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/626798.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++【unordered_map/set的底层实现-哈希表】—含有源代码

文章目录 前言一、unordered_map/unordered_set容器&#xff08;1&#xff09;unordered_map容器介绍及使用&#xff08;2&#xff09;unordered_set容器介绍及使用&#xff08;3&#xff09;它们和map/set对比 二、容器底层结构&#xff08;1&#xff09;哈希表概念&#xff0…

分布式算法之一致性 Hash 算法

tip&#xff1a;作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 &#x1f495;&#x1f495; 推荐&#xff1a;体系化学习Java&#xff08;Java面试专题&#…

第35步 机器学习实战DLC:不平衡数据处理(下)

失踪人口回归的第二期&#xff0c;继续说一说用PSM处理不平衡数据。 一、啥叫PSM PSM全称为Propensity Score Matching&#xff0c;翻译过来就是倾向匹配得分&#xff0c;为了省流&#xff0c;让小Chart介绍一下&#xff1a; 放到我们的数据就是&#xff1a;根据某个特征&…

架构师需要看透公司的用户心智定位

一个架构师要站在用户的角度去思考架构的规划和设计。把注意力放在用户身上&#xff0c;已经有无数案例证明是可以带来重大商业和技术突破的。 很多创业公司&#xff0c;从初创到倒闭&#xff0c;都没搞清楚自己的目标人群和心智。如果一个公司&#xff0c;能锁定目标人群及其…

7个最佳WooCommerce跨境电商社交媒体插件

在互联的早期&#xff0c;您通常可以将产品直接放到网上并出售。但在今天你必须进行营销和做广告。如果没有包括社交媒体在内的可持续营销策略&#xff0c;您的商店可能会被忽视。值得高兴的是&#xff0c;有很多 WooCommerce跨境电商社交媒体插件可以用来传播信息&#xff0c;…

【CMake 入门与进阶(5)】 CMakeLists.txt 语法规则基础及部分常用指令-续(附使用代码)

project project命令用于设置工程名称&#xff1a; # 设置工程名称为 HELLO project(HELLO)执行这个之后会引入两个变量&#xff1a;HELLO_SOURCE_DIR 和 HELLO_BINARY_DIR&#xff0c;注意这两个变量名的前缀就是工程名称&#xff0c;HELLO_SOURCE_DIR 变量指的是 HELLO 工程…

华为推出首款全栈自主数据库 GaussDB,你怎么看?

鸿蒙套壳&#xff0c;鸿蒙套壳完了ERP套&#xff0c;ERP套壳&#xff0c;ERP套壳完了数据库套壳&#xff0c;数据库套壳完了…… 犹记得GaussDB之前一直宣传是基于PostgreSQL研发而来&#xff0c;不知道今天为啥摇身一变为首款全栈自主分布式数据库了。 基于开源研发改不恶心。…

智能设备管理系统

传统设备实施管理难点&#xff1a; 1、日常工作繁琐&#xff0c;手动纸质记录和 Excel 管理设备数据麻烦&#xff0c;后期难以汇总管理&#xff0c;且数据易丢失。 2、需核对设备巡检、保养、故障维修记录&#xff0c;手动更新设备状态和最近维修时间等。 3、无法实时获取设备最…

大学生网络工程想走网络安全方向该怎么规划?

明确需求,确定方向 网络安全 网络安全 是一个很广的概念&#xff0c;涉及的岗位也是非常多的&#xff0c;有安全服务、安全运维、渗透测试、web安全、安全开发、安全售前等等。可以看看下面每个岗位的要求与自身兴趣能力匹配度再决定最适合自己的方向。 渗透测试/Web安全工程师…

开启人机协作新时代:协作机器人的应用与展望

原创 | 文 BFT机器人 01 蓄势待发&#xff0c;产业变革新引擎 近年来&#xff0c;在政策扶持、资本助推和技术创新的共同作用下&#xff0c;产业迎来发展黄金期。日前&#xff0c;各行各业正经历产业智能化转型&#xff0c;机器人市场规模不断扩大&#xff0c;发展前景广阔&…

万宾建筑结构健康监测系统方案

建筑结构健康监测是现代建筑工程领域的重要措施之一。通过实时监测和评估建筑物的结构状态&#xff0c;可以及早发现潜在的问题&#xff0c;保障建筑物的安全性和稳定性。 随着城市化进程的加速和建筑规模的扩大&#xff0c;建筑结构的安全性和稳定性越来越受到关注。然而&…

chatgpt赋能python:Python快速打开:如何提高Python执行速度

Python 快速打开&#xff1a;如何提高 Python 执行速度 介绍 Python 是一种解释型语言&#xff0c;由于其简洁易读&#xff0c;广泛用于数据科学、机器学习、Web 开发等领域。然而&#xff0c;它的执行速度相对较慢&#xff0c;这通常是由于其解释器中面临的硬件资源限制以及…

如何查看docker下的mysql版本

进入运行的mysql的容器 docker exec -it mysqlserver bash 标红的位置可以是我们运行的别名&#xff0c;也可以为id 我们想连接mysql服务时报错了 我们看下配置文件 cat /etc/my.cnf 可以看到配置文件的sock文件位置并不在/var/lib/mysql文件夹中 这里又两种办法 1.直接修改…

JVM--方法区元空间

前言 本篇对java的JVM线程共享内存中的方法区进行系统性的讲解。 1、方法区&元空间概念 方法区是《Java虚拟机规范》中规定的一个内存区域&#xff0c;它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。 元空间是方法区的实现。方法…

python基础----09-----类、对象、魔法方法、封装、继承、类型注解、多态、数据分析案例

一 初识对象 说白了就是类的实例化&#xff0c;类是一个抽象层的定义。 例如下面class Student就是定义的一个类&#xff0c;它是抽象层&#xff0c;然后stu_1 Student()&#xff0c;我们根据类创建了一个对象&#xff0c;就是对类的实例化&#xff0c;这个实例化对象我们是可…

paas云底座-数字化转型,你真的了解么

云底座是什么&#xff1f; 如图 底座其实就是一个基础打个比方&#xff1a; 把底座看成一块土地&#xff0c;我们在这块土地上可以盖楼房&#xff0c;可以挖一个游泳池&#xff0c;可以开一家饭店 也就是说我们这块土地可以开发很多东西言归正传 云底座其实就是数字化转型的“底…

【快速幂】-迭代法:详解

何为快速幂&#xff1f; 我们经常会计算&#xff1a;。STL中有自带的pow函数&#xff0c;如果当n很大的时候&#xff0c;那么一定会TLE。 因此&#xff0c;我们需要另一种求值的方法&#xff1a;快速幂&#xff01; 快速幂有两种做法&#xff1a;1&#xff1a;递归 2…

谷歌云 | 宣布跨云互连:无缝连接到您的所有云

【本文由Cloud Ace整理发布&#xff0c;Cloud Ace 是谷歌云全球战略合作伙伴&#xff0c;拥有 300 多名工程师&#xff0c;也是谷歌最高级别合作伙伴&#xff0c;多次获得 Google Cloud 合作伙伴奖。作为谷歌托管服务商&#xff0c;我们提供谷歌云、谷歌地图、谷歌办公套件、谷…

1 软件测试基本概念

文章目录 课程目标1. 入门前的7个基础问题2. 软件测试基本概念2.1 需求的概念2.1.1需求的基本概念2.1.2 从软件测试人员角度看需求2.1.3 为什么需求对软件测试人员如此重要&#xff1f;2.1.4 如何才可以深入理解被测试软件的需求 2.2 bug的概念(了解)2.3测试用例的概念2.3.1 概…

AI读心术

近期&#xff0c;德克萨斯大学奥斯汀分校的神经科学家们展开了一场「AI」实验&#xff0c;利用人工智能聊天机器人ChatGPT&#xff0c;将大脑活动转化为文字信息。 参与实验的志愿者&#xff0c;在进行长达20小时的「训练」后&#xff0c;成功被「AI」识别出正在进行的活动。按…