Hystrix框架2--超时
timeout
在调用第三方服务时有些情况需要对服务响应时间进行把控,当超时的情况下进行fallback的处理
下面来看下超时的案例
public class CommandTimeout extends HystrixCommand<String> {
private final String name;
public CommandTimeout(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
@Override
protected String run() {
System.out.println("aaaa");
try {
//sleep10秒强制超时,默认超时时间是1s
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run end");
return "";
}
@Override
protected String getFallback() {
return "Hello Failure " + name + "!";
}
}
接下来是测试方法
@Test
public void testSynchronous() throws InterruptedException {
System.out.println(new CommandHelloWorld("World").execute());
}
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at hystrix.CommandHelloWorld.run(CommandHelloWorld.java:32)
at hystrix.CommandHelloWorld.run(CommandHelloWorld.java:1)
...
run end
Hello Failure World!
可以看到sleep被强制interrupted,并且调用的输出也变成了fallback方法的返回值
如何查看是哪里调用的interrupt方法
这里顺便说下如何看是哪个方法调用的interrupt
根据stackoverflow的一个答案,没有直接的方法来断点到interrupt的方法,只能通过在Thread的interrupt方法上打断点,再反向看栈信息得知哪里中断当前线程。
如何改变timeout设置
在HystrixCommand的够着方法中可以在第二个参数配置一个timeout的毫秒数
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"),1000000000);
this.name = name;
}
这个构造方法是在调用AbastractCommand的构造方法时将毫秒数配置在CommandProperties中,如下:
super(group, null, null, null, null, HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(executionIsolationThreadTimeoutInMilliseconds), null, null, null, null, null, null);
Hystrix的timeout是怎么运行的
在运行对应的command时,Hystrix会通过HystrixObservableTimeoutOperator注册一个Timer到一个定时线程池中,当超时后会启用一个HystrixTimer线程来interruptCommand的执行
//创建一个TimerListener
public Reference<TimerListener> addTimerListener(final TimerListener listener) {
startThreadIfNeeded();
// add the listener
Runnable r = new Runnable() {
@Override
public void run() {
try {
listener.tick();
} catch (Exception e) {
logger.error("Failed while ticking TimerListener", e);
}
}
};
//通过ScheduledThreadPoolExecutor在到达超时时间时运行上面的listener.tick,而时间是从listener的getIntervalTimeInMilliseconds方法中获得的
ScheduledFuture<?> f = executor.get().getThreadPool().scheduleAtFixedRate(r, listener.getIntervalTimeInMilliseconds(), listener.getIntervalTimeInMilliseconds(), TimeUnit.MILLISECONDS);
//返回包含timer的Reference,在任务在规定时间内完成是用于cancel超时处理
return new TimerReference(listener, f);
}
//下面是上面listener的定义
TimerListener listener = new TimerListener() {
@Override
public void tick() {
// if we can go from NOT_EXECUTED to TIMED_OUT then we do the timeout codepath
// otherwise it means we lost a race and the run() execution completed or did not start
//这里使用CAS的操作将将状态设置为TIME_OUT,使用CAS的原因是如果运行成功而timeout没有被取消时不会标记任务超时
if (originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) {
// report timeout failure
originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT, originalCommand.commandKey);
// shut down the original request
//内部会取消当前并调用fallback
s.unsubscribe();
timeoutRunnable.run();
//if it did not start, then we need to mark a command start for concurrency metrics, and then issue the timeout
}
}
@Override
public int getIntervalTimeInMilliseconds() {
//这里从command的配置中获得配置的超时时间
return originalCommand.properties.executionTimeoutInMilliseconds().get();
}
};
上面是Command超时后的处理操作,当Command在时间内完成时会调用TimeReference的clear方法,内部调用了future的cancel来取消timer的超时任务
private static class TimerReference extends SoftReference<TimerListener> {
private final ScheduledFuture<?> f;
//保存scheduledFuture
TimerReference(TimerListener referent, ScheduledFuture<?> f) {
super(referent);
this.f = f;
}
@Override
public void clear() {
super.clear();
// stop this ScheduledFuture from any further executions
//停止scheduledFuture
f.cancel(false);
}
}
Hystrix框架2--超时的更多相关文章
- Hystrix框架3--线程池
线程池 在Hystrix中Command默认是运行在一个单独的线程池中的,线程池的名称是根据设定的ThreadPoolKey定义的,如果没有设置那么会使用CommandGroupKey作为线程池. 这 ...
- Hystrix框架1--入门
介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...
- Java并发框架——AQS超时机制
AQS框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性 ...
- springcloud(五) Hystrix 降级,超时
分布式系统中一定会遇到的一个问题:服务雪崩效应或者叫级联效应什么是服务雪崩效应呢? 在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务,比如:商品详情展示服务会依赖商品服务, 价格服务 ...
- Hystrix框架5--请求缓存和collapser
简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...
- Hystrix框架4--circuit
circuit 在Hystrix调用服务时,难免会遇到异常,如对方服务不可用,在这种情况下如果仍然不停地调用就是不必要的,在Hystrix中可以配置使用circuit,当达到一定程度错误,就会自动调用 ...
- Hystrix 框架
雪崩效应的产生原因:当一个服务突然受到高并发的请求,tomcat服务器承受不了的情况下会产生服务堆积,可能导致其他的服务也不可用. 服务保护:当服务产生堆积的时候,对服务实现保护功能. 服务隔离:每个 ...
- Spring Cloud之Hystrix服务保护框架
服务保护利器 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的 ...
- Hystrix多个线程池切换执行超时带来的问题(图解)
线程池切换带来的超时问题 上图有什么问题: Controller的Hystrx线程池已经到了超时时间,而FeignClient的Hystrx线程池还没到超时时间. 场景: Controller ...
随机推荐
- vue学习之旅
大纲: 属性 事件 循环 指令 交互 过滤器 模板 计算属性 自定义过滤器和指令 组件(父子组件之间的通讯) 路由和多层路由以及占位槽slot等其他 vue-loader和模块加载(webpack)等 ...
- 运用泛型,冒泡排序实现JDK引用类型数组的排序
public class Utils { public static <T extends Comparable<T>> void sortList(List<T> ...
- JS简单解决并发量
经常在写代码的时候碰到这样的场景:页面初始化时显示loading页,同时启动多个ajax并发请求获取数据,当每个ajax请求返回时结束loading. 举个例子,一个下订单的页面,要查询常用地址信息. ...
- select2 清空数据
最近用select2插件,发现用jquery重置不好使,最后搜罗了一把发现下面这个方法可以间接的实现,有空还得看看插件的API $('#integratorId').select2('data', n ...
- solr schema.xml文档节点配置
首先,讲解一下/usr/local/solr/collection1/conf/schema.xml的配置,此文档功能类似于配置索引数据库. Field:类似于数据库字段的属性(此文统一使用用“字段” ...
- 修改radio与check样式
一般的radio与check的样式很难看,这个时候就需要我们自己修改其样式 逻辑思维: 1.用label包裹input标签以及样式标签,然后将radio定位到界面以外,设置样式标签的样式 2.使用伪类 ...
- mysql+ssh 配置(转载)
Mysql+ssh配置 一.Linux平台间mysql+ssh配置 本机地址为:192.168.189.133 mysql服务器地址为:192.168.189.139 linux命令行下使用ssh命令 ...
- [ACM训练] 算法初级 之 搜索算法 之 深度优先算法DFS (POJ 2251+2488+3083+3009+1321)
对于深度优先算法,第一个直观的想法是只要是要求输出最短情况的详细步骤的题目基本上都要使用深度优先来解决.比较常见的题目类型比如寻路等,可以结合相关的经典算法进行分析. 常用步骤: 第一道题目:Dung ...
- PHP获取二维数组中的指定若干列【同array_column】
PHP5.3以上 用到了array_map 使用匿名函数进行处理 代码: <?php function array_col($arr = array(), $idx = 0, $newidx ...
- pointer-events 使用场景
最近做一个简单移动web功能,可以左右滑动切换功能.如下图: 但是用户不知道可以滑动切换,所以需要提示用户可以滑动切换,那就添加了一个滑动动画. 滑动动画在最上层,所以当显示滑动提示显示的时候,用户切 ...