zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    字符串比较
    LOOP AT SCREEN
    Trunc的日期用法
    【ABAP】SELECT-ENDSELECT尽量不要用
    【转】Abap For all entries in 使用
    01如何创建sequence:
    abap --MOVE-CORRESPONDING
    Abap 常用变量
    StringBuffer的用法
    Spring事务的传播方式
  • 原文地址:https://www.cnblogs.com/cowboys/p/7660993.html
Copyright © 2011-2022 走看看