1. 程式人生 > >Hystrix-限流及其實戰

Hystrix-限流及其實戰

一、基本概念

Hystrix把一個分散式系統的某一個服務打造成一個高可用的服務最重要的手段之一就是對資源隔離,即通過限流來限制對某一服務的訪問量,比如說對mysql的訪問,為了避免過大的流量直接請求mysql服務,hystrix通過執行緒池或者訊號量技術進行限流訪問。

在《Hystrix-基本概念》中,我們瞭解到Hystrix的兩種隔離技術:執行緒池和訊號量。也分析了在什麼樣的場景下使用執行緒池和訊號量,通常來說執行緒池資源隔離技術一般用於對依賴服務的網路請求訪問,需要解決timeout問題。訊號量則適合對內部的一些比較複雜的業務邏輯訪問,不涉及任何的網路請求,當併發量超過計數器指定值時,直接拒絕。

執行緒池隔離的最大優點在於:任何一個依賴服務都可以被隔離在自己的執行緒池內,即使自己的執行緒池資源填滿了,也不會影響任何其他的服務呼叫。最大缺點在於:增加了cpu的開銷,除了tomcat本身的呼叫執行緒之外,還有hystrix自己管理的執行緒池。每個command的執行都依託一個獨立的執行緒,會進行排隊,排程,還有上下文切換。

二、限流實驗

1、建立command

public class CommandReject extends HystrixCommand<String> {
  private String tag;

  public CommandReject(String tag) {
    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandReject"))
        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()//
            .withCoreSize(5)// 設定執行緒池大小
            .withMaxQueueSize(2))// 設定最大等待佇列大小
        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()//
            .withExecutionTimeoutInMilliseconds(3000)));// 設定timeout時長,預設1000,一個command執行超出這個時間,就被認為是timeout
    this.tag = tag;
  }

  @Override
  protected String run() throws Exception {
    // command的執行等待1s
    Thread.sleep(1000);
    return tag;
  }

  @Override
  protected String getFallback() {
    return "降級處理";
  }
}

2、執行command

public class CommandRejectTest {

  public static void main(String[] args) throws Exception {
    for (int i = 0; i < 10; i++) {
      new TestThread(i).start();
    }

  }

  private static class TestThread extends Thread {

    private int index;

    public TestThread(int index) {
      this.index = index;
    }

    @Override
    public void run() {
      CommandReject breaker = new CommandReject("success");
      System.out.println("第" + (index + 1) + "次請求,結果為:" + breaker.execute());
    }

  }
}

3、執行結果

我們設定了執行緒池的大小為5,然後最大等待佇列的大小為2,同時設定了timeout時長為3000毫秒,這是為了避免command執行發生timeout。然後我們模擬了10個併發量,那麼理論上來說有7個是正常執行,3個應該是直接被限流走fallback降級處理。而實驗的結果也剛好符合我們的預期。