博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hystrix框架2--超时
阅读量:6412 次
发布时间:2019-06-23

本文共 4323 字,大约阅读时间需要 14 分钟。

timeout

在调用第三方服务时有些情况需要对服务响应时间进行把控,当超时的情况下进行fallback的处理

下面来看下超时的案例

public class CommandTimeout extends HystrixCommand
{ 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 + "!"; }}

接下来是测试方法

@Testpublic 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 endHello Failure World!

可以看到sleep被强制interrupted,并且调用的输出也变成了fallback方法的返回值

如何查看是哪里调用的interrupt方法

这里顺便说下如何看是哪个方法调用的interrupt

根据的一个答案,没有直接的方法来断点到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的执行

//创建一个TimerListenerpublic Reference
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
{ 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); }}

转载于:https://www.cnblogs.com/resentment/p/5892769.html

你可能感兴趣的文章
在Linux服务器、客户端中构建密钥对验证进行远程连接
查看>>
揪出MySQL磁盘消耗迅猛的真凶
查看>>
和“C”的再遇
查看>>
linux 的日志系统
查看>>
[转]一个python‘非多态’的问题
查看>>
一键安装kubernetes 1.13.0 集群
查看>>
Java内存模型
查看>>
第一讲 机器学习中的数学
查看>>
RabbitMq的集群搭建
查看>>
asp.net web常用控件FileUpload(文件上传控件)
查看>>
动态网页的建立
查看>>
参数展开与特殊字符
查看>>
linux下使用nginx搭建流媒体服务器
查看>>
解读MySQL驱动加载逻辑
查看>>
Python的time模块(一)
查看>>
Spring控制器注解
查看>>
根据日期分组,查询数量、总量等信息
查看>>
spring boot + mybatis 同时访问多数据源
查看>>
Linux服务器(CentOS)安装SVN(subversion)教程
查看>>
Oracle官网下载jdk 版本
查看>>