hystrix服務降級(3)


Hystrix使用fallback機制很簡單,繼承HystrixCommand只需重寫getFallback(),繼承HystrixObservableCommand只需重寫resumeWithFallback(),比如上篇文章的HelloWorldHystrixCommand加上下面代碼片段:

@Override
protected String getFallback() {
    return "fallback: " + name;
}

 fallback實際流程是當run()/construct()被觸發執行時或執行中發生錯誤時,將轉向執行getFallback()/resumeWithFallback()

 結合下圖,4種情況(出現異常,超時,熔斷,線程池已滿)將觸發fallback:

①run()方法中出現異常(非HystrixBadRequestException異常)或者出現超時()觸發fallback()

public class HystrixFallbackNomal extends HystrixCommand<String>{

  private final String name;

   public HystrixFallbackNomal(String name) {
	super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
	this.name = name;
  }

  @Override
  public String run() throws Exception {
	/*---------------會觸發fallback的case-------------------*/
    	// 無限循環,實際上屬於超時
    /*	int j = 0;
    	while (true) {
    		j++;
    	}*/
	Thread.sleep(1000);
    	
    	// 除零異常
    	// int i = 1/0;
    	
    	// 主動拋出異常
//      throw new HystrixTimeoutException();
//      throw new RuntimeException("this command will trigger fallback");
//      throw new Exception("this command will trigger fallback");
//    	throw new HystrixRuntimeException(FailureType.BAD_REQUEST_EXCEPTION, commandClass, message, cause, fallbackException);
        
    	/*---------------不會觸發fallback的case-------------------*/
    	// 被捕獲的異常不會觸發fallback
//    	try {
//    		throw new RuntimeException("this command never trigger fallback");
//    	} catch(Exception e) {
//    		e.printStackTrace();
//    	}
        
    	// HystrixBadRequestException異常由非法參數或非系統錯誤引起,不會觸發fallback,也不會被計入熔斷器
        //throw new HystrixBadRequestException("HystrixBadRequestException is never trigger fallback");
        
     //return name;
	}
@Override protected String getFallback() {   return "fallback: " + name; }   }
}

 ②熔斷觸發fallback()

/**
 * 熔斷機制相當於電路的跳閘功能,例如:我們可以配置熔斷策略為當請求錯誤比例在10s內>50%時,該服務將進入熔斷狀態,后續請求都會進入fallback
 * CircuitBreakerRequestVolumeThreshold設置為3,意味着10s內請求超過3次就觸發熔斷器(10s這個時間暫時不可配置)
 * run()中無限循環使命令超時進入fallback,10s內請求超過3次,將被熔斷,進入降級,即不進入run()而直接進入fallback
 * 如果未熔斷,但是threadpool被打滿,仍然會降級,即不進入run()而直接進入fallback
 */
public class HystrixFallbackCircuitBreaker extends HystrixCommand<String>{
	private final String name;

    public HystrixFallbackCircuitBreaker(String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CircuitBreakerTestGroup"))  
                .andCommandKey(HystrixCommandKey.Factory.asKey("CircuitBreakerTestKey"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("CircuitBreakerTest"))
                .andThreadPoolPropertiesDefaults(	// 配置線程池
                		HystrixThreadPoolProperties.Setter()
                		.withCoreSize(200)	// 配置線程池里的線程數,設置足夠多線程,以防未熔斷卻打滿threadpool
                )
                .andCommandPropertiesDefaults(	// 配置熔斷器
                		HystrixCommandProperties.Setter()
                		.withCircuitBreakerEnabled(true)
                		.withCircuitBreakerRequestVolumeThreshold(3)
                		.withCircuitBreakerErrorThresholdPercentage(80)
//	                		.withCircuitBreakerForceOpen(true)	// 置為true時,所有請求都將被拒絕,直接到fallback
//	                		.withCircuitBreakerForceClosed(true)	// 置為true時,將忽略錯誤
//	                		.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)	// 信號量隔離
//	                		.withExecutionTimeoutInMilliseconds(5000)
                )
        );
        this.name = name;
    }

    @Override
    protected String run() throws Exception {
    	System.out.println("running run():" + name);
    	int num = Integer.valueOf(name);
    	if(num < 10) {	// 直接返回
    	  return name;
    	} else {	// 無限循環模擬超時
    	  int j = 0;
          while (true) {
          j++;
          }
    	}
//	return name;
    }

    @Override
    protected String getFallback() {
        return "CircuitBreaker fallback: " + name;
    }
}
    @Test
       public void testFallbackCricuitBreaker() throws IOException {
       	for(int i = 0; i < 50; i++) {
	     try {
	        System.out.println("===========" + new HystrixFallbackCircuitBreaker(String.valueOf(i)).execute());
	     } catch(Exception e) {
	           System.out.println("run()拋出HystrixBadRequestException時,被捕獲到這里" + e.getCause());
	     }
       	}

       	System.out.println("------開始打印現有線程---------");
       	Map<Thread, StackTraceElement[]> map=Thread.getAllStackTraces();
       	for (Thread thread : map.keySet()) {
	  System.out.println(thread.getName());
	}
       	System.out.println("thread num: " + map.size());
       	
       	System.in.read();
       }               

③線程池已滿,觸發fallback()

public class HystrixThreadPoolFallback extends HystrixCommand<String>{

  private final String name;

    public HystrixThreadPoolFallback(String name) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ThreadPoolTestGroup"))  
                .andCommandKey(HystrixCommandKey.Factory.asKey("testCommandKey"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("ThreadPoolTest"))
                .andCommandPropertiesDefaults(
                	HystrixCommandProperties.Setter()
                		.withExecutionTimeoutInMilliseconds(5000)
                )
                .andThreadPoolPropertiesDefaults(
                	HystrixThreadPoolProperties.Setter()
                		.withCoreSize(3)	// 配置線程池里的線程數
                )
        );
        this.name = name;
    }

  @Override
    protected String run() throws Exception {
    	System.out.println(name);
	TimeUnit.MILLISECONDS.sleep(2000);
	return name;
    }

    @Override
    protected String getFallback() {
        return "fallback: " + name;
    }
}

 

 @Test
    public void testThreadPool() throws IOException {
    	for(int i = 0; i < 10; i++) {
          try {
        	Future<String> future = new HystrixThreadPoolFallback("Hlx"+i).queue();
          } catch(Exception e) {
        	System.out.println("run()拋出HystrixBadRequestException時,被捕獲到這里" + e.getCause());
          }
    	}
    	for(int i = 0; i < 20; i++) {
          try {
        	System.out.println("===========" + new HystrixThreadPoolFallback("Hlx"+i).execute());
          } catch(Exception e) {
        	System.out.println("run()拋出HystrixBadRequestException時,被捕獲到這里" + e.getCause());
          }
    	}
    	try {
    	  TimeUnit.MILLISECONDS.sleep(2000);
    	}catch(Exception e) {}
    	System.out.println("------開始打印現有線程---------");
    	Map<Thread, StackTraceElement[]> map=Thread.getAllStackTraces();
    	for (Thread thread : map.keySet()) {
			System.out.println(thread.getName());
		}
    	System.out.println(map);
    	System.out.println("thread num: " + map.size());

    	System.in.read();
    }

 參考文獻:http://www.jianshu.com/p/b9af028efebb


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM