线程池

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

这样每个Command都可以拥有自己的线程池而不会互相影响,同时线程池也可以很好地控制Command的并发量。

设置线程池配置

可以使用Setter来初始化Command在Setter中可以配置线程池的大小和等待队列的长度:

public CommandHelloWorld(String name) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
//配置线程池相关属性,队列大小和线程数
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withMaxQueueSize(10).withCoreSize(10))
//配置运行相关参数如运行超时时间
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100000000)));
//super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
}

在运行时Hystrix会使用ConcurrencyStrategy来创建线程池以及对应的队列,下面是默认的HystrixConcurrencyStrategy

//线程池中的等待队列
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
/*
* We are using SynchronousQueue if maxQueueSize <= 0 (meaning a queue is not wanted).
* <p>
* SynchronousQueue will do a handoff from calling thread to worker thread and not allow queuing which is what we want.
* <p>
* Queuing results in added latency and would only occur when the thread-pool is full at which point there are latency issues
* and rejecting is the preferred solution.
*/
if (maxQueueSize <= 0) {
//当配置的queue大小小于等于0使用SynchronousQueue,也就是如果没有空闲线程就导致失败
return new SynchronousQueue<Runnable>();
} else {
//其他情况使用阻塞Queue来配置等待队列
return new LinkedBlockingQueue<Runnable>(maxQueueSize);
}
}
//创建线程池的方法
public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
ThreadFactory threadFactory = null;
if (!PlatformSpecific.isAppEngine()) {
threadFactory = new ThreadFactory() {
protected 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 {
threadFactory = PlatformSpecific.getAppEngineThreadFactory();
}
//通过配置的信息创建线程池
return new ThreadPoolExecutor(corePoolSize.get(), maximumPoolSize.get(), keepAliveTime.get(), unit, workQueue, threadFactory);
}

当然以上是默认的ConcurrencyStrategy,Hystrix中可以通过Plugin配置自定义的Strategy:

HystrixPlugins.getInstance().registerConcurrencyStrategy

但这个Plugin是单例的且register方法只能调用一次,也就是无法设置多个Strategy,如果想要使用不同的Strategy只能在方法内部使用一定逻辑来完成。

Semaphore

还有一种不用ThreadPool的方法,是配置SEMAPHORE

HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(10).withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)

这种模式会在主线程自身运行(在调用queue时就会执行)。同时可以通过withExecutionIsolationSemaphoreMaxConcurrentRequests设置并发的数量。

fallback

当配置的等待队列满了的时候Hystrix会直接调用Command的fallback方法。

下面来看下各种情况下代码是执行在哪个线程中的

ThreadPool模式下

超时调用getFallback:Timer线程

线程池队列满调用getFallback:主线程

Command出错调用getFallback:Command线程池

Semaphore模式下

超时调用getFallback:Timer线程

并发数满调用getFallback:主线程

Command出错调用getFallback:主线程

总结

在使用Hystrix时要注意各个代码是运行在哪个线程中的,防止在不必要的地方有阻塞的调用,如在fallback中如果有阻塞耗时操作,那么在队列满时会导致主线程阻塞,可以考虑在Fallback中再调用新Command,这时还要考虑使用不同的线程池防止任务互相排队。

Hystrix框架3--线程池的更多相关文章

  1. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  2. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  3. 并发新特性—Executor 框架与线程池

    兰亭风雨 · 更新于 2018-11-14 09:00:31 并发新特性-Executor 框架与线程池 Executor 框架简介 在 Java 5 之后,并发编程引入了一堆新的启动.调度和管理线程 ...

  4. hystrix熔断器之线程池

    隔离 Hystrix有两种隔离方式:信号量和线程池. 线程池隔离:对每个command创建一个自己的线程池,执行调用.通过线程池隔离来保证不同调用不会相互干扰和每一个调用的并发限制. 信号量隔热:对每 ...

  5. java并发编程(十七)Executor框架和线程池

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17465497   Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动 ...

  6. 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

      Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...

  7. SpringCloud Hystrix熔断之线程池

    服务熔断 雪崩效应:是一种因服务提供者的不可用导致服务调用者的不可用,并导致服务雪崩的过程. 服务熔断:当服务提供者无法调用时,会通过断路器向调用方直接返回一个错误响应,而不是长时间的等待,避免服务雪 ...

  8. 【Java并发编程】:并发新特性—Executor框架与线程池

    Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocur ...

  9. Java的Executor框架和线程池实现原理

    Java的Executor框架 1,Executor接口 public interface Executor { void execute(Runnable command); } Executor接 ...

随机推荐

  1. TProfiler

    下载:访问 TProfiler 的 GitHub 主页,https://github.com/alibaba/TProfiler,点击 Clone or download 按钮的打开下载选项,点击该选 ...

  2. nodejs复习05

    stream 可读流 fs.pause()方法会使处于流动模式的流停止触发data事件,切换到非流动模式并让后续数据流在内部缓冲区 var fs = require('fs') var rs = fs ...

  3. 域名解析服务查询工具dnstracer

    域名解析服务查询工具dnstracer   在访问网站过程中,当用户输入网址后,通常是先解析域名,获取该网站的IP地址.然后,根据IP地址访问对应的网站服务器.所以,域名解析服务器保证域名指向正确的网 ...

  4. C++-数据库【1】-C++连接MSSQL数据库

    测试环境—— 系统:Win7 64bit 编译器:VC++ 2015 数据库:MSSQL 2008 R2 #include <Windows.h> #include <stdio.h ...

  5. 一些关于HTML与CSS的总结与实际应用

    //学习前端也快一年了,觉得有必要好好总结一下这一年来学过的知识.一些是前辈们的精华,文章最后会讲地址一一放出,若原作者有任何介意,请及时联系我删除. 关于DOCTYPE 1.DOCTYPE的作用是什 ...

  6. Visual Studio 常用快捷键

    作为一个使用VisualStudio的程序员,使用快捷键会为你的开发提供助力. 下附个人开发过程中感觉比较实用的快捷键: 开始运行"devenv",启动相应版本的VisualStu ...

  7. Leetcode Valid Anagram

    Given two strings s and t, write a function to determine if t is an anagram of s. For example,s = &q ...

  8. HTTP 使用期及新鲜度算法

    使用期算法: /* * age_value 当代理服务器用自己的头部去响应请求时,Age标明实体产生到现在多长时间了. * date_value HTTP 服务器应答中的Date字段 原始服务器 * ...

  9. 【翻译svg教程 】svg 的坐标系统

    http://tutorials.jenkov.com/svg/svg-coordinate-system.html svg的坐标系统(和大多数计算机绘图的坐标系统)和数学中绘图系统有点不一样 数学/ ...

  10. oracle遍历表更新另一个表(一对多)

    declare cursor cur_test is select t.txt_desig, m.segment_id, s.code_type_direct, case when s.uom_dis ...