hystrix源码之插件
HystrixPlugins
获取并发相关类(HystrixConcurrencyStrategy)、事件通知类(HystrixEventNotifier)、度量信息类(HystrixMetricsPublisher)、Properties配置类(HystrixPropertiesStrategy)、HystrixCommand回调函数类(HystrixCommandExecutionHook)、HystrixDynamicProperties,6类插件。
插件获取:
HystrixPlugins 首先会去properties(HystrixDynamicProperties)配置下需找相应类型的实现类。
private static <T> T getPluginImplementationViaProperties(Class<T> pluginClass, HystrixDynamicProperties dynamicProperties) {
String classSimpleName = pluginClass.getSimpleName();
// Check Archaius for plugin class.
String propertyName = "hystrix.plugin." + classSimpleName + ".implementation";
String implementingClass = dynamicProperties.getString(propertyName, null).get();
....
如果返回null,则通过ServiceLoader获取相应类型的实现类。
private <T> T getPluginImplementation(Class<T> pluginClass) {
T p = getPluginImplementationViaProperties(pluginClass, dynamicProperties);
if (p != null) return p;
return findService(pluginClass, classLoader);
}
private static <T> T findService(
Class<T> spi,
ClassLoader classLoader) throws ServiceConfigurationError { ServiceLoader<T> sl = ServiceLoader.load(spi,
classLoader);
for (T s : sl) {
if (s != null)
return s;
}
return null;
}
如果获取成功,存储变量中。
final AtomicReference<HystrixEventNotifier> notifier = new AtomicReference<HystrixEventNotifier>();
public HystrixEventNotifier getEventNotifier() {
if (notifier.get() == null) {
// check for an implementation from Archaius first
Object impl = getPluginImplementation(HystrixEventNotifier.class);
if (impl == null) {
// nothing set via Archaius so initialize with default
notifier.compareAndSet(null, HystrixEventNotifierDefault.getInstance());
// we don't return from here but call get() again in case of thread-race so the winner will always get returned
} else {
// we received an implementation from Archaius so use it
notifier.compareAndSet(null, (HystrixEventNotifier) impl);
}
}
return notifier.get();
}
获取HystrixDynamicProperties对象,有点不同,首先使用HystrixDynamicPropertiesSystemProperties配置来需找相应类型的实现类。第二如果查询不同会默认使用Archaius,如果依然没有Archaius支持,会使用HystrixDynamicPropertiesSystemProperties。
private static HystrixDynamicProperties resolveDynamicProperties(ClassLoader classLoader, LoggerSupplier logSupplier) {
HystrixDynamicProperties hp = getPluginImplementationViaProperties(HystrixDynamicProperties.class,
HystrixDynamicPropertiesSystemProperties.getInstance());
if (hp != null) {
logSupplier.getLogger().debug(
"Created HystrixDynamicProperties instance from System property named "
+ "\"hystrix.plugin.HystrixDynamicProperties.implementation\". Using class: {}",
hp.getClass().getCanonicalName());
return hp;
}
hp = findService(HystrixDynamicProperties.class, classLoader);
if (hp != null) {
logSupplier.getLogger()
.debug("Created HystrixDynamicProperties instance by loading from ServiceLoader. Using class: {}",
hp.getClass().getCanonicalName());
return hp;
}
hp = HystrixArchaiusHelper.createArchaiusDynamicProperties();
if (hp != null) {
logSupplier.getLogger().debug("Created HystrixDynamicProperties. Using class : {}",
hp.getClass().getCanonicalName());
return hp;
}
hp = HystrixDynamicPropertiesSystemProperties.getInstance();
logSupplier.getLogger().info("Using System Properties for HystrixDynamicProperties! Using class: {}",
hp.getClass().getCanonicalName());
return hp;
}
HystrixConcurrencyStrategy
并发相关的策略类。
获取线程池,实际根据配置创建ThreadPoolExecutor。
/**
获取线程池*/
public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
final ThreadFactory threadFactory = getThreadFactory(threadPoolKey);
final int dynamicCoreSize = corePoolSize.get();
final int dynamicMaximumSize = maximumPoolSize.get();
if (dynamicCoreSize > dynamicMaximumSize) {
logger.error("Hystrix ThreadPool configuration at startup for : " + threadPoolKey.name() + " is trying to set coreSize = " +
dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " +
dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value");
return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime.get(), unit, workQueue, threadFactory);
} else {
return new ThreadPoolExecutor(dynamicCoreSize, dynamicMaximumSize, keepAliveTime.get(), unit, workQueue, threadFactory);
}
} public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
final ThreadFactory threadFactory = getThreadFactory(threadPoolKey);
final boolean allowMaximumSizeToDivergeFromCoreSize = threadPoolProperties.getAllowMaximumSizeToDivergeFromCoreSize().get();
final int dynamicCoreSize = threadPoolProperties.coreSize().get();
final int keepAliveTime = threadPoolProperties.keepAliveTimeMinutes().get();
final int maxQueueSize = threadPoolProperties.maxQueueSize().get();
final BlockingQueue<Runnable> workQueue = getBlockingQueue(maxQueueSize);
if (allowMaximumSizeToDivergeFromCoreSize) {
final int dynamicMaximumSize = threadPoolProperties.maximumSize().get();
if (dynamicCoreSize > dynamicMaximumSize) {
logger.error("Hystrix ThreadPool configuration at startup for : " + threadPoolKey.name() + " is trying to set coreSize = " +
dynamicCoreSize + " and maximumSize = " + dynamicMaximumSize + ". Maximum size will be set to " +
dynamicCoreSize + ", the coreSize value, since it must be equal to or greater than the coreSize value");
return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
} else {
return new ThreadPoolExecutor(dynamicCoreSize, dynamicMaximumSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
}
} else {
return new ThreadPoolExecutor(dynamicCoreSize, dynamicCoreSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
}
}
private static ThreadFactory getThreadFactory(final HystrixThreadPoolKey threadPoolKey) {
if (!PlatformSpecific.isAppEngineStandardEnvironment()) {
return new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(0); @Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "hystrix-" + threadPoolKey.name() + "-" + threadNumber.incrementAndGet());
thread.setDaemon(true);
return thread;
} };
} else {
return PlatformSpecific.getAppEngineThreadFactory();
}
}
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
if (maxQueueSize <= 0) {
return new SynchronousQueue<Runnable>();
} else {
return new LinkedBlockingQueue<Runnable>(maxQueueSize);
}
}
在执行callable前提供用户对callable进行分装
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return callable;
}
获取HystrixRequestVariable
public <T> HystrixRequestVariable<T> getRequestVariable(final HystrixRequestVariableLifecycle<T> rv) {
return new HystrixLifecycleForwardingRequestVariable<T>(rv);
}
HystrixCommandExecutionHook
hystrix命令执行过程中的回调接口,提供了一下回调接口。
/**
在命令执行前被调用*/
public <T> void onStart(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
当接收到数据时被调用*/
public <T> T onEmit(HystrixInvokable<T> commandInstance, T value) {
return value; //by default, just pass through
} /**
*当命令异常时被调用
* @since 1.2
*/
public <T> Exception onError(HystrixInvokable<T> commandInstance, FailureType failureType, Exception e) {
return e; //by default, just pass through
} /**
*当执行成功后被调用
* @since 1.4
*/
public <T> void onSuccess(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
在线程池执行命令前执行*/
public <T> void onThreadStart(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
在线程池执行完成后调用*/
public <T> void onThreadComplete(HystrixInvokable<T> commandInstance) {
// do nothing by default
} /**
当开始执行命令时调用*/
public <T> void onExecutionStart(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
当执行命令emits a value时调用
*
* @param commandInstance The executing HystrixInvokable instance.
* @param value value emitted
*
* @since 1.4
*/
public <T> T onExecutionEmit(HystrixInvokable<T> commandInstance, T value) {
return value; //by default, just pass through
} /**
执行抛出异常时调用*/
public <T> Exception onExecutionError(HystrixInvokable<T> commandInstance, Exception e) {
return e; //by default, just pass through
} /**
当调用命令成功执行完调用
* @since 1.4
*/
public <T> void onExecutionSuccess(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
* Invoked when the fallback method in {@link HystrixInvokable} starts.
*
* @param commandInstance The executing HystrixInvokable instance.
*
* @since 1.2
*/
public <T> void onFallbackStart(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
* Invoked when the fallback method in {@link HystrixInvokable} emits a value.
*
* @param commandInstance The executing HystrixInvokable instance.
* @param value value emitted
*
* @since 1.4
*/
public <T> T onFallbackEmit(HystrixInvokable<T> commandInstance, T value) {
return value; //by default, just pass through
} /**
* Invoked when the fallback method in {@link HystrixInvokable} fails with an Exception.
*
* @param commandInstance The executing HystrixInvokable instance.
* @param e exception object
*
* @since 1.2
*/
public <T> Exception onFallbackError(HystrixInvokable<T> commandInstance, Exception e) {
//by default, just pass through
return e;
} /**
* Invoked when the user-defined execution method in {@link HystrixInvokable} completes successfully.
*
* @param commandInstance The executing HystrixInvokable instance.
*
* @since 1.4
*/
public <T> void onFallbackSuccess(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
如果从缓存中获取数据时调用*/
public <T> void onCacheHit(HystrixInvokable<T> commandInstance) {
//do nothing by default
} /**
当取消挂载时被调用
* @since 1.5.9
*/
public <T> void onUnsubscribe(HystrixInvokable<T> commandInstance) {
//do nothing by default
}
HystrixEventNotifier
hystrix命令执行过程中,接收相应的事件通知。
/**
接收到消息后执行
接受一下消息:
RESPONSE_FROM_CACHE如果该command从缓存中获取数据
CANCELLED 如果command在完成前unsubscrible
EXCEPTION_THROWN 如果command出现异常
EMIT 如果command发送数据
THREAD_POOL_REJECTED 如果线程池抛出reject异常
FAILURE 执行失败异常
FALLBACK_EMIT执行fallback返回数据
FALLBACK_SUCCESS执行fallback成功
FALLBACK_FAILURE执行fallback发生异常
FALLBACK_REJECTION超过信号量,fallback未被执行。
FALLBACK_MISSING
SEMAPHORE_REJECTED信号量模型执行被拒绝。
SHORT_CIRCUITED熔断
*/
public void markEvent(HystrixEventType eventType, HystrixCommandKey key) {
// do nothing
}
/**
* Called after a command is executed using thread isolation.
* Will not get called if a command is rejected, short-circuited etc.*/
public void markCommandExecution(HystrixCommandKey key, ExecutionIsolationStrategy isolationStrategy, int duration, List<HystrixEventType> eventsDuringExecution) {
// do nothing
}
HystrixMetricsPublisher
HystrixMetricsPublisherFactory使用该插件来创建HystrixMetricsPublisherCommand、HystrixMetricsPublisherThreadPool、HystrixMetricsPublisherCollapser,并调用相应的initialize方法,这些类用来向第三方publish hystrix的metrics信息。
private final ConcurrentHashMap<String, HystrixMetricsPublisherThreadPool> threadPoolPublishers = new ConcurrentHashMap<String, HystrixMetricsPublisherThreadPool>(); /* package */ HystrixMetricsPublisherThreadPool getPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) {
// attempt to retrieve from cache first
HystrixMetricsPublisherThreadPool publisher = threadPoolPublishers.get(threadPoolKey.name());
if (publisher != null) {
return publisher;
}
// it doesn't exist so we need to create it
publisher = HystrixPlugins.getInstance().getMetricsPublisher().getMetricsPublisherForThreadPool(threadPoolKey, metrics, properties);
// attempt to store it (race other threads)
HystrixMetricsPublisherThreadPool existing = threadPoolPublishers.putIfAbsent(threadPoolKey.name(), publisher);
if (existing == null) {
// we won the thread-race to store the instance we created so initialize it
publisher.initialize();
// done registering, return instance that got cached
return publisher;
} else {
// we lost so return 'existing' and let the one we created be garbage collected
// without calling initialize() on it
return existing;
}
}
HystrixPropertiesStrategy
创建HystrixCommandProperties、HystrixThreadPoolProperties、HystrixCollapserProperties、HystrixTimerThreadPoolProperties
/**
创建HystrixCommandProperties*/
public HystrixCommandProperties getCommandProperties(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {
return new HystrixPropertiesCommandDefault(commandKey, builder);
}/**
创建HystrixThreadPoolProperties*/
public HystrixThreadPoolProperties getThreadPoolProperties(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter builder) {
return new HystrixPropertiesThreadPoolDefault(threadPoolKey, builder);
}/**
创建HystrixCollapserProperties*/
public HystrixCollapserProperties getCollapserProperties(HystrixCollapserKey collapserKey, HystrixCollapserProperties.Setter builder) {
return new HystrixPropertiesCollapserDefault(collapserKey, builder);
}
/**
创建HystrixTimerThreadPoolProperties*/
public HystrixTimerThreadPoolProperties getTimerThreadPoolProperties() {
return new HystrixPropertiesTimerThreadPoolDefault();
}
hystrix源码之插件的更多相关文章
- hystrix源码之概述
概述 hystrix核心原理是通过代理执行用户命令,记录命令执行的metrics信息,通过这些metrics信息进行降级和熔断. 源码结构包括一下几个部分: 熔断器 熔断器就是hystrix用来判断调 ...
- WeMall微商城源码报名插件Apply的主要源码
WeMall微信商城源码报名插件Apply,用于商城的签到系统,分享了部分比较重要的代码,供技术员学习参考 AdminController.class.php <?php namespace A ...
- WeMall微商城源码投票插件Vote的主要源码
WeMall微信商城源码投票插件Vote,用于商城的签到系统,分享了部分比较重要的代码,供技术员学习参考 AdminController.class.php <?php namespace Ad ...
- Hystrix源码解析
1. Hystrix源码解析 1.1. @HystrixCommand原理 直接通过Aspect切面来做的 1.2. feign hystrix原理 它的本质原理就是对HystrixCommand的动 ...
- MyBatis 源码分析 - 插件机制
1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...
- MyBatis 源码篇-插件模块
本章主要描述 MyBatis 插件模块的原理,从以下两点出发: MyBatis 是如何加载插件配置的? MyBatis 是如何实现用户使用自定义拦截器对 SQL 语句执行过程中的某一点进行拦截的? 示 ...
- 【一起学源码-微服务】Hystrix 源码一:Hystrix基础原理与Demo搭建
说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一个系列文章讲解了Feign的源码,主要是Feign动态 ...
- Maven 依赖调解源码解析(二):如何调试 Maven 源码和插件源码
本文是系列文章<Maven 源码解析:依赖调解是如何实现的?>第二篇,主要介绍如何调试 Maven 源码和插件源码.系列文章总目录参见:https://www.cnblogs.com/xi ...
- 分享非常漂亮的WPF界面框架源码及插件化实现原理
在上文<分享一个非常漂亮的WPF界面框架>中我简单的介绍了一个界面框架,有朋友已经指出了,这个界面框架是基于ModernUI来实现的,在该文我将分享所有的源码,并详细描述如何基于Mod ...
随机推荐
- 走正确的路 - IT业没有护城河 - 机器翻译新锐Deepl
最近发生了一件很令我震惊的事情:新的一个机器翻译网站出现了 - www.deepl.com (DeepL 或许会成为你今年首选的翻译工具) 机器翻译早就是红海市场了.我就不从1954年IBM发布俄翻英 ...
- java自动拆装箱
介绍 Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装类型的相互转换操作.(关于基本类型与包装类型之前有记录过https://www.cnblogs.com/xiuzhublog/p/12 ...
- 11.oracle 事务
一.什么是事务事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败.如:网上转账就是典型的要用事务来处理,用于保证数据的 ...
- 原生js实现 vue的数据双向绑定
原生js实现一个简单的vue的数据双向绑定 vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时 ...
- 提升布局能力!理解 CSS 的多种背景及使用场景和技巧
CSS background是最常用的CSS属性之一.然而,并不是所有开发人员都知道使用多种背景.这段时间都在关注使用多种背景场景.在本文中,会详细介绍background-image`属性,并结合图 ...
- 计算机网络-链路层(2)多路访问控制协议(multiple access control protocol)
单一共享广播信道,如果两个或者两个以上结点同时传输,会互相干扰(interference) 冲突(collision):结点同时接收到两个或者多个信号→接收失败! MAC协议采用分布式算法决定结点如何 ...
- 简述HBase的Bulk Load
为什么用Bulk load? 批量加载数据到HBase集群,有很多种方式,比如利用 HBase API 进行批量写入数据.使用Sqoop工具批量导数到HBase集群.使用MapReduce批量导入等等 ...
- 大型Kubernetes集群的资源编排优化
背景 云原生这个词想必大家应该不陌生了,容器是云原生的重要基石,而Kubernetes经过这几年的快速迭代发展已经成为容器编排的事实标准了.越来越多的公司不论是大公司还是中小公司已经在他们的生产环境中 ...
- php高效读取和写入
/** * 删除非空目录里面所有文件和子目录 * @param string $dir * @return boolean */ function fn_rmdir($dir) { //先删除目录下的 ...
- Linux文件描述符与重定向
文件描述符可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作. 当Linux启动的时候会默认打开三个文件描述符,分别是: 标 ...