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. 【iOS [[UIApplication sharedApplication] delegate]】运用

    之前想要拿到app的窗口,我们通常的写法是: [UIApplication sharedApplication].keyWindow 这种写法之前一直也觉得是正确的,没什么问题,而且网上大多数的博客或 ...

  2. 【iOS Instrument性能优化集】

    iOS Instrument性能优化集 1.UIImage缓存取舍 在项目代码中看到大量使用如下代码: UIImage使用 在Main Thread中发现不同动画场景中Image IO 开销和耗时所占 ...

  3. 打包如何打包额外文件,比如Sqlite数据库的db文件

    http://aigo.iteye.com/blog/2278224 Project Settings -> packaging -> Packaging选项中,有多个设置项来设置打包时要 ...

  4. Codeforces Round #345 (Div. 1) A. Watchmen

    A. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  5. [转] nodemon 基本配置与使用

    在开发环境下,往往需要一个工具来自动重启项目工程,之前接触过 python 的 supervisor,现在写 node 的时候发现 supervisior 在很多地方都有他的身影,node 也有一个 ...

  6. Python for Infomatics 第14章 数据库和SQL应用一(译)

    14.1 什么是数据库 数据库一种存储结构数据的文件.绝大多数数据库类似字典——映射键和值的关系.最大的区别是数据库是保存在硬盘或其它永久性的存储上,所以在程序结束后它仍然存在.而保存在内存中的字典容 ...

  7. Linux Crontab语法

    Crontab语法 Lists 链表值 : 逗号,表示并列,要依次序;Examples:"1,2,5,9", "0-4,8-12". Ranges of num ...

  8. python基础04 运算

    数学运算 print 2+2  #加法 print 1.3-4 #剪法 print 3*5 #乘法 print 4.5/1.5 #除法 print 3**2   #乘方 print 10%3   #求 ...

  9. 简述JavaScript对象、数组对象与类数组对象

    问题引出 在上图给出的文档中,用JavaScript获取那个a标签,要用什么办法呢?相信第一反应一定是使用document.getElementsByTagName('a')[0]来获取.同样的,在使 ...

  10. BZOJ2506: calc

    Description            给一个长度为n的非负整数序列A1,A2,…,An.现有m个询问,每次询问给出l,r,p,k,问满足l<=i<=r且Ai mod p = k的值 ...