1 隔离策略 - ExecutionIsolationStrategy
执行HystrixCommand时使用
指定HystrixCommand.run()的资源隔离策略。
资源隔离,要解决的最核心的问题,就是将多个依赖服务的调用分别隔离到各自资源池内。避免对某个依赖服务的调用,因为依赖服务的接口调用的延迟或者失败,导致服务所有线程资源全部耗费在该服务的接口调用上。
1.1 THREAD - 线程池隔离
线程池隔离技术,并非指控制类似tomcat web容器的线程。严格意义说,hystrix的线程池隔离技
术,控制tomcat线程的执行。线程池满后,确保tomcat的线程不会因为依赖服务的接口调用延迟或故障,被hang住,fallback , ms。tomcat其他的线程不会卡死,快速返回,然后可以支撑其他的事情。
线程池和信号量做资源隔离、限流、容量的限制,默认的容量都是10。
线程池隔离技术是用自己的线程去执行调用的。
信号量隔离技术,是直接让tomcat的线程去调用依赖服务的。
默认的策略为线程池。
THREAD:在单独的线程上执行HystrixCommand#run方法,使用线程池大小限制并发
基于线程池
HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)
优点
支持排队和超时
支持异步调用
不足
线程调用会产生额外的性能开销。
容易由于创建大量线程而 OOM,所以 sentinel 只支持信号量隔离。
适用场景
适合绝大多数的场景,线程池,对依赖服务的网络请求的调用和访问,超时这种问题。
不受信客户
有限扇出
1.2 SEMAPHORE - 信号量隔离
SEMAPHORE:在调用线程上执行HystrixCommand#run方法,使用信号量许可计数限制
基于信号量
HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
线程池机制,每个command运行在一个线程中,限流是通过线程池的大小来控制的
信号量机制,command是运行在调用线程中,但是通过信号量的容量来进行限流
优点
轻量,无额外开销。
不足
不支持任务排队和主动超时
不支持异步调用
适用场景
适合访问不是对外部依赖的访问,而是对内部比较复杂业务逻辑的访问。
但像这种访问,系统内部代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流即可。
因为不需要去捕获类似超时的问题,算法效率要求不是太高。并发量突然太高,因为这里稍微耗时一些,导致很多线程卡在这里的话,不太好,所以进行一个基本的资源隔离和访问,避免内部复杂的低效率代码,导致大量线程夯死。
受信客户
高扇出(网关)
高频高速调用
使用信号量场景,通常是针对超大并发量,每个服务实例每秒都几百QPS。
此时如果用线程池,线程一般不会太多,可能撑不住高并发。要撑住,可能要耗费大量线程资源,那么就用信号量,来限流保护。
一般用信号量常见于那种基于纯内存服务,而不涉及到任何网络访问请求。
netflix有100+的command运行在40+的线程池中,只有少数command是不运行在线程池中的,就是从纯内存中获取一些元数据,或者是对多个command包装起来的facacde command,是用信号量限流的。
比如缓存服务,可能会将部分量特别少,访问又特别频繁的一些数据,放在纯内存。
一般我们在获取到商品数据之后,都要去获取商品是属于哪个地理位置,省,市,卖家的
可能在自己的纯内存中,比如就一个Map去获取。对于这种直接访问本地内存的逻辑,比较适合用信号量做一下简单的隔离。
优点在于,不用自己管理线程池,不用担心超时,信号量做隔离的话,性能会相对高。
坑点
2 command名称 & command组
2.1 command名称
每个command,都可设置自己的名称,同时可以设置一个自己的组。
private static final Setter cachedSetter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")) .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")); public CommandHelloWorld(String name) { super(cachedSetter); this.name = name; }
2.2 command group
默认情况下,因为就是通过command group来定义一个线程池,而且还会通过command group聚合一些监控和报警信息。
同一command group中的请求,都会进入同一个线程池中。