`
ieye
  • 浏览: 32082 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

动态代理实现规则降级

阅读更多

在业务系统中实现对已有的各个业务校验规则Rule的增强,因为太多的Rule实现依赖了外部系统而变得不可控,并且系统对规则基本定位成强校验,这样我们系统的可用性以及稳定性会被外部系统所左右,于是提出了对规则可以动态降级,实现运行时绕过一些规则的校验(当然,需要在业务容忍一致性和系统可用性之间权衡)。同事的想法:提供一个基类来负责执行是否降级的功能,然后每个具体的实现类继承这个基类,在执行真正的规则校验逻辑之前,调用父类的方法判断是否走校验。我觉得这样做的问题有两点,首先,规则本身不应该去关注降级的问题,这样规则的职责更加纯粹。其次,之前已经有很多规则实现,这样做要去改变之前的规则实现,而且是通过继承的方式来修改,同时对每个实现的改动都是类似的,比较机械化。考虑了下,决定使用动态代理对规则实现降级管理。代码实现很简单:

public class DegraderableRuleWrapper implements FactoryBean, BeanNameAware {
	
	private final static Logger LOG = LoggerFactory.getLogger(DegraderableRuleWrapper.class);
	
	private final static String ITEM_RULE_NAME_SKIP_NAME = "com.***.ruleSkipNameList";
	/**
	 * 需要跳过的规则列表
	 */
	private static Set<String> skipRuleNameList = Sets.newHashSet();
	
	/**
	 * 用于分隔字符串的工具类
	 */
	private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults();
	
	private Rule target;
	
	private String ruleName; 
	
	private Object delegate;
	
	public void setTarget(Rule target) {
		this.target = target;
		//ruleName = target.getClass().getSimpleName();
	}
	
	@Override
	public void setBeanName(String name) {
		ruleName = name;
	}
	
	@Override
	public Object getObject() throws Exception {
		
		if (delegate == null) {
			delegate = createProxy();
		}
		return delegate;
	}

	private Object createProxy() {
		@SuppressWarnings("unchecked")
		Class<?>[] allInterfaces = (Class<?>[]) ClassUtils.getAllInterfaces(target.getClass()).toArray(new Class<?>[0]);
		Object wrapperedRule = Proxy.newProxyInstance(target.getClass().getClassLoader(), allInterfaces, new SwitchListener());
		
		LOG.warn("create a degraderableRule for rule {}.", ruleName);
		
		return wrapperedRule;
	}

	@Override
	public Class<? extends Rule> getObjectType() {
		return Rule.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}
	
	static{
		initialSkipRuleListAndListenChange();
	}
	
	private static void initialSkipRuleListAndListenChange() {
		/*
		 * 开始并不主动拉取,而是注册监听,等待异步回调,减少应用启动时间。
		 */
		Diamond.addListener(ITEM_RULE_NAME_SKIP_NAME, Constants.DEFAULT_GROUP, new ManagerListenerAdapter() {
			@Override
			public void receiveConfigInfo(String configInfo) {
				LOG.warn("Got new skipRuleNameList, " + configInfo);
				Iterable<String> ruleNames = SPLITTER.split(configInfo);
				Set<String> newSkipRuleNames = Sets.newHashSet(ruleNames);
				skipRuleNameList = newSkipRuleNames;
			}
		});
	}

	private class SwitchListener implements InvocationHandler {

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			if (skipRuleNameList.contains(ruleName)) {
				LOG.warn("Rule {} is in skipList, skip it.", ruleName);
				return RuleResult.successResult();
			}
			return method.invoke(target, args);
		}
		
	}

}

 实现中使用了spring的factorybean,beanname,google的guava工具类以及淘宝开源的diamond集中式静态配置管理工具。PS:diamond主要是实现对集群的配置管理,其他的方式也很多,比如使用zookeeper也可以,当然使用存储+线程定时轮询变化(其实diamond的实现方式就很类似,只不过加上了比较多的容灾功能)也OK。

对于实现需要注意的是这行代码:

Class<?>[] allInterfaces = (Class<?>[]) ClassUtils.getAllInterfaces(target.getClass()).toArray(new Class<?>[0]);

 开始的时候直接使用

target.getClass().getInterfaces()

 发现继承过来的实现,获取不到类实现的接口,也算是细节的一个点吧。

 

使用这个规则的地方只需要配置下这个bean即可,配置方式如下:

<bean id="testPlatformRule" class="com.***.rule.DegraderableRuleWrapper">
		<property name="target">
			<bean class="com.***.rule.impl.TestPlatformRule" />
		</property>
	</bean>

 这样其他地方在引用这个bean的时候就已经是进行了降级管理的Rule了,这样实现了降级功能的统一管理和规则本身的职责单一性。

分享到:
评论

相关推荐

    WH-1000XM3降级包.zip

    3. `mdrproxy.js` 和 `mdrproxy.ts`:这些可能是实现降级过程的代理服务,使用JavaScript(`.js`)和TypeScript(`.ts`)编写。TypeScript是JavaScript的一个超集,提供静态类型检查和更强大的代码结构。 4. `mdr.js...

    代理商管理办法-.doc

    3. **降级或取消资格**:连续两年未达销售目标、损害企业利益或违反规则的代理商将被降级或取消资格。 **四、违规行为处理** 包括但不限于:主动取消资格、违法违约、未经许可转移资格、跨区销售、恶意竞争、截留...

    Sentinel新技术特性解密.pdf

    - **K8S CRD 动态配置规则**:通过 Kubernetes Custom Resource Definition,可以动态配置 Sentinel 规则,进一步提升运维效率。 - **可靠性与弹性**:Sentinel 将继续强化与 Kubernetes HPA 的集成,结合多种指标...

    基于微服务架构的平台化服务框架的设计与实现

    例如,使用Spring Cloud Netflix的Hystrix组件可以实现熔断和降级策略,Zuul或Spring Cloud Gateway作为API网关则提供了服务治理的能力。 【软件工程流程】在设计和实现微服务架构的过程中,遵循软件工程的规范,...

    基于dubbo实现的rpc框架RPC

    4. **智能路由**: 可根据业务规则动态调整请求路由,实现灰度发布、蓝绿部署等高级功能。 5. **灵活扩展**: 支持SPI(Service Provider Interface)机制,允许用户自定义扩展点,以适应不同的业务需求。 6. **多种...

    Dubbo服务框架 v2.7.9-源码.zip

    3. **Proxy**:提供了基于JDK动态代理和CGLIB的接口代理实现。 4. **Cluster**:负责将多个服务提供者实例进行聚合,实现负载均衡。 5. **Router**:定义了服务路由规则,可以根据条件选择不同的服务提供者。 6. **...

    SpringCloud——路由器和过滤器(Zuul)

    4. **熔断与降级**:结合Hystrix,Zuul可以实现服务间的熔断和降级策略,提高系统的容错性。 5. **负载均衡**:Zuul可以集成Ribbon进行客户端负载均衡,自动分发请求到不同的服务实例。 **Zuul的过滤器** 1. **Pre...

    spring cloud 配置源码.zip

    在源码中,你可以看到Hystrix如何通过设置降级策略、熔断机制和限流规则来保护系统稳定。降级策略是在服务不可用时提供一个默认的备选方案,避免完全阻塞;熔断机制则是在一段时间内,如果调用失败次数超过预设阈值...

    zuuldemoo.rar

    5. **服务降级**:在服务不可用或者性能下降时,Zuul 可以提供降级策略,保证系统的稳定运行。 在“zuuldemoo”项目中,我们可以期待看到以下关键配置和代码结构: 1. **Eureka 客户端配置**:项目中的服务实例...

    1000道 互联网Java工程师面试题 485页 .pdf

    接口绑定是指使用接口作为定义SQL语句的文件,Mybatis通过动态代理实现接口绑定。插件运行原理是通过JDK的动态代理在Mybatis执行SQL前后进行拦截。 ### ZooKeeper #### 核心概念 ZooKeeper是一个开源的分布式协调...

    详解详 nginx代理代 socket.io服务踩坑

    然而,在实际部署中,由于WebSocket与HTTP协议的差异,我们往往需要借助像Nginx这样的反向代理服务器来实现Socket.IO服务的代理。本文将深入探讨在使用Nginx代理Socket.IO服务时可能遇到的问题以及解决方案。 首先...

    21-面试宝典(进一般互联网公司必看).docx

    * 动态代理(cglib 与 JDK) * Spring 事务的实现方式 * Spring 事务的底层原理 * 如何自定义注解实现功能 * Spring MVC 的运行流程 * Spring MVC 的启动流程 * Spring 的单例实现原理 * Spring 框架中用到的设计...

    Spring Cloud(zuul)使用例子.zip

    4. **服务降级与熔断**:通过集成Hystrix,Zuul可以实现服务降级和熔断策略,防止因某个服务故障导致整个系统崩溃。 5. **安全控制**:Zuul可以作为统一的安全入口,进行权限验证、API访问控制等,保护后端服务不受...

    Sentinel-1.7.2的jar包与源码

    sentinel-envoy-rls-token-server-1.7.2.jar 是与 Envoy 集成的 Sentinel 相关组件,Envoy 是一款高性能的服务网格代理,Sentinel 通过这个组件实现了与 Envoy 的资源预留系统(RLS,Resource Reservation System)...

    基于spring cloud的云阅卷系统.zip

    Eureka作为服务注册与发现中心,Hystrix实现服务降级和熔断,Zuul或Gateway作为API网关,负责路由转发和权限校验。 四、关键技术 1. **Spring Boot**:作为基础框架,简化了Spring应用的初始搭建以及开发过程,...

    61管理设计篇之-服务网络1

    7. **路由与治理**:灵活的路由规则,实现灰度发布、金丝雀测试等高级功能。 8. **服务治理**:动态调整服务间的依赖关系,支持微服务的弹性扩展和缩容。 Service Mesh的出现是为了解决传统服务治理中的痛点,比如...

    1000道 互联网大厂Java工程师面试题.pdf

    7. Dao接口的工作原理:MyBatis通过代理生成接口的实现类,利用动态代理机制完成接口与Mapper XML的绑定。 8. Mybatis分页原理及插件:利用limit语句进行分页,插件可以通过拦截器链进行处理。 9. Mybatis如何封装...

    Dubbo高级视频教程

    - **动态代理机制**:Dubbo内部使用JDK动态代理或CGLIB实现远程接口和服务动态代理。 - **集群容错策略**:包括Failover、Failfast、Failsafe等不同的集群容错方案。 #### 三、Dubbo配置详解 - **dubbo.xml配置...

    sentinel-dashboard-1.7.2.jar 和 sentinel-envoy-rls-token-server-1.7.2.jar

    Envoy 是一款流行的服务网格代理,而 RLS 功能允许 Envoy 在接收到请求时,先向 Sentinel Token 服务器申请令牌,只有获得令牌的服务实例才能继续处理请求,以此实现流控。 1. **Token 分发**:当客户端(Envoy)...

    CTO讲解微店的架构之道

    尽管TCC引入了一定的性能开销和运维成本,但通过动态降级策略,能够在保证业务连续性的同时,应对不同的服务级别需求。 5. **其他技术细节**:包括使用lua进行安全防护,支持多种编程语言,结合静态和动态扫描工具...

Global site tag (gtag.js) - Google Analytics