隔离分为线程池隔离和信号量隔离,通过判断线程池或者信号量是否已满,超出容量的请求直接降级,从而达到限流的作用

线程池隔离:

给每个接口提供一个独立的线程池:
image.png
优点:

  • 任何的服务都会被隔离在自己的线程池内,即使自己的线程池资源被填满,也不会影响其他服务
  • 当依赖的服务重新恢复时,可通过清理线程池,瞬间恢复服务的调用,但是如果是tomcat线程池被填满,再恢复就会很麻烦
  • 由于线程池中线程个数有限制,所以也就解决了限流的问题

缺点:
增加了cpu的开销,不仅仅有tomcat线程池,还需要有hystrix线程池

代码:

  1. //---------------------线程隔离
  2. //groupKey 一组command,如果没有配这个,相同的groupkey会使用同一个线程池
  3. @HystrixCommand(groupKey = "thread1-group",commandKey = "thread1",threadPoolKey = "thread1-group",threadPoolProperties = {
  4. @HystrixProperty(name="coreSize",value = "8"),
  5. @HystrixProperty(name="maxQueueSize",value="5")
  6. })
  7. public void thread1(){
  8. System.out.println(Thread.currentThread().getName());
  9. }
  10. @HystrixCommand(groupKey = "thread2-group",commandKey = "thread1",threadPoolKey = "thread2-group",threadPoolProperties = {
  11. @HystrixProperty(name="coreSize",value = "8"),
  12. @HystrixProperty(name="maxQueueSize",value="5")
  13. })
  14. public void thread2(){
  15. System.out.println(Thread.currentThread().getName());
  16. }

image.png

如果多个api使用同一个线程池,那么coreSize如何设置?
答: 走第一个api设置的
代码:cloud-provider-hystrix-payment8001

线程隔离代码:

1.不加Hystrix线程隔离,默认的使用tomcat线程池
image.png

  1. public void thread1(){
  2. System.out.println(a++);
  3. try {
  4. Thread.sleep(20000);
  5. }catch (Exception e){
  6. System.out.println(111);
  7. }
  8. System.out.println(Thread.currentThread().getName());
  9. }
  10. public void thread2(){
  11. System.out.println(Thread.currentThread().getName());
  12. }

2.添加Hystrix线程池分组

  1. @HystrixCommand(groupKey = "thread1-group",commandKey = "thread1",threadPoolKey = "thread1-group",commandProperties={
  2. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="40000")
  3. },threadPoolProperties = {
  4. @HystrixProperty(name="coreSize",value = "8"),
  5. // @HystrixProperty(name="allowMaximumSizeToDivergeFromCoreSize",value = "true"),
  6. // @HystrixProperty(name = "maximumSize",value="10"),
  7. @HystrixProperty(name="maxQueueSize",value="5")
  8. })
  9. public void thread1(){
  10. System.out.println(a++);
  11. try {
  12. Thread.sleep(20000);
  13. }catch (Exception e){
  14. System.out.println(111);
  15. }
  16. System.out.println(Thread.currentThread().getName());
  17. }
  18. @HystrixCommand(
  19. groupKey = "thread2-group",commandKey = "thread2",threadPoolKey = "thread2-group",threadPoolProperties = {
  20. @HystrixProperty(name="coreSize",value = "8"),
  21. // @HystrixProperty(name="maxQueueSize",value="5")
  22. })
  23. public void thread2(){
  24. System.out.println(Thread.currentThread().getName());
  25. }

image.png
结论: 他们之间的线程来自不同的线程池,不会互相受影响,
由于设定的排队的队列为 5 所以 8+ 5 最多有 13个请求
否则就报错了,但是在 13个以内的请求是不会报错的

另外一点就是允许的延时时间

image.png
3.threadPoolKey 相同的 用同一个线程池,如果threadPoolKey不写 默认是 groupKey的值

@HystrixCommand(groupKey = "thread1-group",commandKey = "thread1",threadPoolKey = "hyf111",commandProperties={
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="40000")
    },threadPoolProperties = {
            @HystrixProperty(name="coreSize",value = "8"),
            @HystrixProperty(name="maxQueueSize",value="5")
    })
    public void thread1(){

        System.out.println(a++);
        try {
            Thread.sleep(20000);
        }catch (Exception e){
            System.out.println(111);
        }

        System.out.println(Thread.currentThread().getName());
    }

    @HystrixCommand(groupKey = "thread2-group",commandKey = "thread1",threadPoolKey = "hyf111",threadPoolProperties = {
            @HystrixProperty(name="coreSize",value = "8"),
            @HystrixProperty(name="maxQueueSize",value="5")
    })
    public void thread2(){
        System.out.println(Thread.currentThread().getName());
    }

结果:
image.png

信号量隔离:

其实就是一个计数器,加入设定为5 那么就是最多同时有5个来访问
image.png
由于Hystrix默认使用线程池做线程隔离,使用信号量隔离需要显示地将属性execution.isolation.strategy设置为ExecutionIsolationStrategy.SEMAPHORE,同时配置信号量个数,默认为10。客户端需向
依赖服务发起请求时,首先要获取一个信号量才能真正发起调用,由于信号量的数量有限,当并发请求量超过信号量个数时,后续的请求都会直接拒绝,进入fallback流程

image.png
线程池和信号量都支持熔断和限流。相比线程池,信号量不需要线程切换,因此避免了不必要的开销。但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回,即可能出现长时间等待。线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。