一个HystrixPlugins引起的debug问题

项目场景:

近期在使用Spring Cloud Alibaba时,因为在微服务中上下文使用ThreadLocal时遇到了失效的问题,所以引入了ThreadLocalHystrixConcurrencyStrategy来处理这个问题,没想到引入后每次项目进行debug时都会跳转到异常


问题描述:

例如:在使用debug模式时启动Application:

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
@EnableBinding(MQSource.class)
public class OrderServiceStarter {
	public static void main(String[] args) {
		HystrixPlugins.getInstance().registerConcurrencyStrategy(new ThreadLocalHystrixConcurrencyStrategy());
		SpringApplication.run(OrderServiceStarter.class, args);
	}
}

项目启动时会跳转至该错误

Class ConfigurationManagerprivate static Properties loadCascadedProperties(String configName) throws IOException {
        String defaultConfigFileName = configName + ".properties";
        if (instance == null) {
            instance = getConfigInstance();
        }
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        URL url = loader.getResource(defaultConfigFileName);
        if (url == null) {
	        //异常跳转至此,缺少hystrix-plugins.properties
            throw new IOException("Cannot locate " + defaultConfigFileName + " as a classpath resource.");
        }
        Properties props = getPropertiesFromFile(url);
        String environment = getDeploymentContext().getDeploymentEnvironment();
        if (environment != null && environment.length() > 0) {
            String envConfigFileName = configName + "-" + environment + ".properties";
            url = loader.getResource(envConfigFileName);
            if (url != null) {
                Properties envProps = getPropertiesFromFile(url);
                if (envProps != null) {
                    props.putAll(envProps);
                }
            }
        }
        return props;
    }

原因分析:

debug观察后发现是因为缺少hystrix-plugins.properties,配置文件,百思不得其解,明明我们已经在main方法中将对应的插件注册进去了,为啥还会去扫描hystrix-plugins.properties,故而翻阅源码!


话不多讲,直接找到 HystrixPlugins
Class HystrixPlugins:

    public HystrixEventNotifier getEventNotifier() {
        if (notifier.get() == null) {
            //首先检查Archaius的实现,如果有手动注册,则先采用手动注册
            Object impl = getPluginImplementation(HystrixEventNotifier.class);
            if (impl == null) {
                // 没有设置通过Archaius,采用默认初始化
                notifier.compareAndSet(null, HystrixEventNotifierDefault.getInstance());
            } else {
                notifier.compareAndSet(null, (HystrixEventNotifier) impl);
            }
        }
        return notifier.get();
    }
    
 	private <T> T getPluginImplementation(Class<T> pluginClass) {
 		//此处已经很明显了
        T p = getPluginImplementationViaProperties(pluginClass, dynamicProperties);
        if (p != null) return p;        
        return findService(pluginClass, classLoader);
    }
    
	@SuppressWarnings("unchecked")
    private static <T> T getPluginImplementationViaProperties(Class<T> pluginClass, HystrixDynamicProperties dynamicProperties) {
        String classSimpleName = pluginClass.getSimpleName();
        // 看到了这里! 恍然大悟,就是这个东西!
        String propertyName = "hystrix.plugin." + classSimpleName + ".implementation";
        String implementingClass = dynamicProperties.getString(propertyName, null).get();
        if (implementingClass != null) {
            try {
                Class<?> cls = Class.forName(implementingClass);
                cls = cls.asSubclass(pluginClass);
                return (T) cls.newInstance();
            } catch (ClassCastException e) {
                throw new RuntimeException(classSimpleName + " implementation is not an instance of " + classSimpleName + ": " + implementingClass);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(classSimpleName + " implementation class not found: " + implementingClass, e);
            } catch (InstantiationException e) {
                throw new RuntimeException(classSimpleName + " implementation not able to be instantiated: " + implementingClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(classSimpleName + " implementation not able to be accessed: " + implementingClass, e);
            }
        } else {
            return null;
        }
    }

解决方案:

源码解读完后,答案已经摆在眼前了,我直接新建一个hystrix-plugins.properties
将我们具体的实现类写入其中,并添加上我们的测试方法

hystrix.plugin.HystrixConcurrencyStrategy.implementation=com.something.common.hystrix.ThreadLocalHystrixConcurrencyStrategy
public class ThreadLocalHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
	private final static Logger logger = LoggerFactory.getLogger(ThreadLocalHystrixConcurrencyStrategy.class);

	public ThreadLocalHystrixConcurrencyStrategy() {
		log.info("ThreadLocalHystrixConcurrencyStrategy被实例化了");
		System.out.println("ThreadLocalHystrixConcurrencyStrategy被实例化了");
	}

重新debug模式启动项目,不再出现上述错误,大功告成。
同时,观察实例化的时间节点,发现是在该微服务被调用时会进行实例化,这就跟具体实现的内容相关了。

总结:

总而言之,阅读源码的确不可缺少

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值