前面我们学习了Hystrix中的线程隔离,通常我们都采用基于线程池的实现方式,这也是最容易理解的方案。Hystrix还提供了另一种底层实现,那就是信号量隔离。
线程池 vs 信号量的优缺点比较 - 图1
小时候我们就知道“红灯停,绿灯行”,跟着交通信号的指示过马路。信号量也是这么一种放行、禁行的开关作用。它和线程池技术一样,控制了服务可以被同时访问的并发数量,乍一看好像两种技术并没有多大区别,我们接下来比较一下它们在应用场景上的不同之处。

大家来找茬

线程隔离原理

  • 线程池技术:它使用Hystrix自己内建的线程池去执行方法调用,而不是使用Tomcat的容器线程
  • 信号量技术:它直接使用Tomcat的容器线程去执行方法,不会另外创建新的线程,信号量只充当开关和计数器的作用。获取到信号量的线程就可以执行方法,没获取到的就转到fallback

    从性能角度看

  • 线程池技术:涉及到线程的创建、销毁和任务调度,而且CPU在执行多线程任务的时候会在不同线程之间做切换,我们知道在操作系统层面CPU的线程切换是一个相对耗时的操作,因此从资源利用率和效率的角度来看,线程池技术会比信号量慢

  • 信号量技术:由于直接使用Tomcat容器线程去访问方法,信号量只是充当一个计数器的作用,没有额外的系统资源消费,所以在性能方面具有明显的优势

    超时判定

  • 线程池技术:相当于多了一层保护机制(Hystrix自建线程),因此可以直接对“执行阶段”的超时进行判定

  • 信号量技术:只能等待诸如网络请求超时等“被动超时”的情况

    使用场景

    我这里引用Hystrix的官方文档,里面特地讲到了信号量的使用场景:
    Generally the only time you should use semaphore isolation for HystrixCommands is when the call is so high volume (hundreds per second, per instance) that the overhead of separate threads is too high; this typically only applies to non-network calls
    当请求量非常密集,导致线程隔离的开销比较高的时候,建议使用信号量的方式降低负荷,这种情况通常用来应对非网络请求(不需要调用外部服务)。
    根据官方建议,信号量适用在超高并发的非外部接口调用上(还是中文言简意赅),注意“the only time”,意思是官方只建议在上述场景中应用信号量技术,在其他场景上尽量使用线程池做线程隔离。
    除此之外,线程池技术要特别注意ThreadLocal的数据传递作用,由于前后调用不在同一个线程内,也不在父子线程内,所以如果你在业务层面声明了ThreadLocal变量,将无法获取正确的值。

    小结

    这一节我们了解了线程隔离底层的信号量和线程池技术,接下来,带大家玩一个支线剧情,通过Turbine监控Hystrix服务健康度。