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--超时的更多相关文章

  1. Hystrix框架3--线程池

    线程池 在Hystrix中Command默认是运行在一个单独的线程池中的,线程池的名称是根据设定的ThreadPoolKey定义的,如果没有设置那么会使用CommandGroupKey作为线程池. 这 ...

  2. Hystrix框架1--入门

    介绍 在开发应用中或多或少会依赖各种外界的服务,利用各个服务来完成自己的业务需求,现在流行的微服务架构更是离不开各个服务之间的调用,这就导致整体应用的可用性依赖于各个依赖服务的可用性. 比如一个依赖3 ...

  3. Java并发框架——AQS超时机制

    AQS框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性 ...

  4. springcloud(五) Hystrix 降级,超时

    分布式系统中一定会遇到的一个问题:服务雪崩效应或者叫级联效应什么是服务雪崩效应呢? 在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务,比如:商品详情展示服务会依赖商品服务, 价格服务 ...

  5. Hystrix框架5--请求缓存和collapser

    简介 在Hystrix中有个Request的概念,有一些操作需要在request中进行 缓存 在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求. 应用 需要启用 ...

  6. Hystrix框架4--circuit

    circuit 在Hystrix调用服务时,难免会遇到异常,如对方服务不可用,在这种情况下如果仍然不停地调用就是不必要的,在Hystrix中可以配置使用circuit,当达到一定程度错误,就会自动调用 ...

  7. Hystrix 框架

    雪崩效应的产生原因:当一个服务突然受到高并发的请求,tomcat服务器承受不了的情况下会产生服务堆积,可能导致其他的服务也不可用. 服务保护:当服务产生堆积的时候,对服务实现保护功能. 服务隔离:每个 ...

  8. Spring Cloud之Hystrix服务保护框架

    服务保护利器 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的 ...

  9. Hystrix多个线程池切换执行超时带来的问题(图解)

      线程池切换带来的超时问题 ​ 上图有什么问题: Controller的Hystrx线程池已经到了超时时间,而FeignClient的Hystrx线程池还没到超时时间. 场景: Controller ...

随机推荐

  1. 【vuejs小项目——vuejs2.0版本】组件化的开发方式

    对于多张页面需要里存在相同模块,可以进行组建化的开发模式. 例如:此处需要一个评分标准组件,创建一个components/star/star.vue. 在需要引入该组建的页面上 import进去< ...

  2. iOS 删除、重新排序xcdatamodel

    找到Xcode项目文件.xcodeproj,查看包内容. 里面有project.pbxproj,用文本编辑器打开. 找到类似如下内容段: /* Begin XCVersionGroup section ...

  3. Android 照相 滤镜

    android-image-filter 19种相片滤镜,使用也简单,all filters in file BitmapFilter.java : Bitmap newBitmap = Bitmap ...

  4. CEF中select选项错位的解决方法

    使用cef加载页面,移动窗口后选项的位置并不会变化,仍保持上次打开的位置. 经过google查找到这是一个已经解决了的问题:https://bitbucket.org/chromiumembedded ...

  5. 关于Web服务器的认识

    马上就要毕业了,也要开始找工作了,大学写了这么多代码了,却没有好好总结一下常用的概念很是遗憾额,就通过这篇博客记录一下我最常用的一些知识好了. 说到Web服务器,有很多文章都介绍的很好,之前看到一篇非 ...

  6. HDU 5976 数学,逆元

    1.HDU 5976 Detachment 2.题意:给一个正整数x,把x拆分成多个正整数的和,这些数不能有重复,要使这些数的积尽可能的大,输出积. 3.总结:首先我们要把数拆得尽可能小,这样积才会更 ...

  7. bootstrap之HTML模板

    bootstrap之HTML模板 <!DOCTYPE html> <html> <head> <title>Bootstrap 模板</title ...

  8. 国内外三个不同领域巨头分享的Redis实战经验及使用场景

    Redis不是比较成熟的memcache或者Mysql的替代品,是对于大型互联网类应用在架构上很好的补充.现在有越来越多的应用也在纷纷基于Redis做架构的改造.首先简单公布一下Redis平台实际情况 ...

  9. problem-eclipse创建maven项目报错

    Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.5 or one of ...

  10. ubuntu vps 安装 jdk

    Introduction Java is a programming technology originally developed by Sun Microsystems and later acq ...