线程池

在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. filefiter

    1.写一个类继承与FileFilter package com.dream.musicplayer; import <a href="http://lib.csdn.net/base/ ...

  2. 关于jquery简单操作简单表格

    最近在摸索jquery中,想着学习过程中还是记下点自己的东西比较好,不管是日后自己查阅,亦或是对于他人有些许帮助. 也是一件两全其美的事情了. 下面我就简单 贴上自己的html中重要部分了. 具体实现 ...

  3. vim配置及快捷键

    vim+python http://codingpy.com/article/vim-and-python-match-in-heaven/ vim+c++ http://jikaichen.com/ ...

  4. WPF 实现圆形进度条

    项目中用到圆形进度条,首先就想到使用 ProgressBar 扩展一个,在园子里找到迷途的小榔头给出的思路和部分代码,自己加以实现. 进度小于60显示红色,大于60则显示绿色.效果如下: 基本思路: ...

  5. 从零开始山寨Caffe·伍:Protocol Buffer简易指南

    你为Class外访问private对象而苦恼嘛?你为设计序列化格式而头疼嘛? ——欢迎体验Google Protocol Buffer 面向对象之封装性 历史遗留问题 面向对象中最矛盾的一个特性,就是 ...

  6. 关于php-fpm子进程达到上限并且浏览器访问显示504错误

    今天上班遇到一个非常奇怪的事情,公司监控服务器之前都是在正常运行,使用nginx+php-fpm,并且监控服务器上部署这其他部门在使用的几个站点,从早上上班开始发现监控显示页面打不开,各种查找原因,最 ...

  7. android 常用URI

    关于联系人的一些URI: 管理联系人的Uri: ContactsContract.Contacts.CONTENT_URI 管理联系人的电话的Uri: ContactsContract.CommonD ...

  8. OpenGL编程指南(第七版)

    OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...

  9. python使用pdkdf2加盐密码

    from werkzeug.security import generate_password_hash, check_password_hash pw = generate_password_has ...

  10. Ubuntu 14.04(amd64)安装Oracle11g XE(x64)

    下载Oracle安装包 下载地址:Oracle Database Express Edition 11g Release 2 for Linux x64 安装办法 1、建立oracle用户及属主 ad ...