续:
Hystrix使用
1 package com.cjs.example; 2 3 import com.netflix.hystrix.HystrixCommand; 4 import com.netflix.hystrix.HystrixCommandGroupKey; 5 6 public class CommandHelloWorld extends HystrixCommand<String> { 7 8 private String name; 9 10 public CommandHelloWorld(HystrixCommandGroupKey group, String name) { 11 super(group); 12 this.name = name; 13 } 14 15 public CommandHelloWorld(Setter setter, String name) { 16 super(setter); 17 this.name = name; 18 } 19 20 @Override 21 protected String run() throws Exception { 22 if ("Alice".equals(name)) { 23 throw new RuntimeException("出错了"); 24 } 25 return "Hello, " + name; 26 } 27 28 @Override 29 protected String getFallback() { 30 return "Failure, " + name; 31 } 32 33 }
1 package com.cjs.example; 2 3 import com.netflix.hystrix.HystrixCommand; 4 import com.netflix.hystrix.HystrixCommandGroupKey; 5 import com.netflix.hystrix.HystrixCommandProperties; 6 import com.netflix.hystrix.HystrixThreadPoolProperties; 7 import org.junit.Test; 8 import rx.Observable; 9 import rx.Observer; 10 11 import java.util.concurrent.ExecutionException; 12 import java.util.concurrent.Future; 13 14 import static org.junit.Assert.*; 15 import static org.junit.Assert.assertEquals; 16 17 public class CommandHelloWorldTest { 18 19 @Test 20 public void testSync() { 21 HystrixCommandGroupKey hystrixCommandGroupKey = HystrixCommandGroupKey.Factory.asKey("ExampleGroup"); 22 CommandHelloWorld command = new CommandHelloWorld(hystrixCommandGroupKey, "World"); 23 String result = command.execute(); 24 assertEquals("Hello, World", result); 25 } 26 27 @Test 28 public void testAsync() throws ExecutionException, InterruptedException { 29 HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("ExampleGroup"); 30 assertEquals("Hello, Jack", new CommandHelloWorld(groupKey, "Jack").queue().get()); 31 assertEquals("Hello, Rose", new CommandHelloWorld(groupKey, "Rose").queue().get()); 32 33 CommandHelloWorld command = new CommandHelloWorld(groupKey, "Cheng"); 34 Future<String> future = command.queue(); 35 String result = future.get(); 36 assertEquals("Hello, Cheng", result); 37 38 // blocking 39 Observable<String> observable = new CommandHelloWorld(groupKey, "Lucy").observe(); 40 assertEquals("Hello, Lucy", observable.toBlocking().single()); 41 42 // non-blocking 43 Observable<String> observable2 = new CommandHelloWorld(groupKey, "Jerry").observe(); 44 observable2.subscribe(new Observer<String>() { 45 @Override 46 public void onCompleted() { 47 System.out.println("completed"); 48 } 49 50 @Override 51 public void onError(Throwable throwable) { 52 throwable.printStackTrace(); 53 } 54 55 @Override 56 public void onNext(String s) { 57 System.out.println("onNext: " + s); 58 } 59 }); 60 } 61 62 @Test 63 public void testFail() throws ExecutionException, InterruptedException { 64 HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("Group2"); 65 assertEquals("Failure, Alice", new CommandHelloWorld(groupKey,"Alice").execute()); 66 assertEquals("Failure, Alice", new CommandHelloWorld(groupKey,"Alice").queue().get()); 67 } 68 69 @Test 70 public void testProp() { 71 HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("Group3"); 72 73 HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter() 74 .withCoreSize(10) 75 .withMaximumSize(10); 76 77 HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter() 78 .withCircuitBreakerEnabled(true) 79 .withExecutionTimeoutInMilliseconds(100); 80 81 HystrixCommand.Setter setter = HystrixCommand.Setter.withGroupKey(groupKey); 82 setter.andThreadPoolPropertiesDefaults(threadPoolProperties); 83 setter.andCommandPropertiesDefaults(commandProperties); 84 85 assertEquals("Hello, Cheng", new CommandHelloWorld(setter, "Cheng").execute()); 86 87 } 88 }
Spring Boot中使用Hystrix
1. Maven依赖
2. 使用@HystrixCommand注解
1 package com.cjs.example; 2 3 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; 5 import org.apache.commons.lang.StringUtils; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RestController; 8 9 @RestController 10 @RequestMapping("/greet") 11 public class GreetController { 12 13 @HystrixCommand(fallbackMethod = "onError", 14 commandProperties = { 15 @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"), 16 @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"), 17 @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), 18 @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2")}, 19 threadPoolProperties = { 20 @HystrixProperty(name = "coreSize", value = "5"), 21 @HystrixProperty(name = "maximumSize", value = "5"), 22 @HystrixProperty(name = "maxQueueSize", value = "10") 23 }) 24 @RequestMapping("/sayHello") 25 public String sayHello(String name) { 26 try { 27 Thread.sleep(200); 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 return "Hello, " + name; 32 } 33 34 @HystrixCommand 35 @RequestMapping("/sayHi") 36 public String sayHi(String name) { 37 if (StringUtils.isBlank(name)) { 38 throw new RuntimeException("name不能为空"); 39 } 40 return "Good morning, " + name; 41 } 42 43 /** 44 * 如果fallback方法的参数和原方法参数个数不一致,则会出现FallbackDefinitionException: fallback method wasn't found 45 */ 46 public String onError(String name) { 47 return "Error!!!" + name; 48 } 49 50 }
3. Hystrix配置
1 package com.cjs.example; 2 3 import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; 5 import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; 6 import org.springframework.boot.web.servlet.ServletContextInitializer; 7 import org.springframework.boot.web.servlet.ServletRegistrationBean; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 11 import javax.servlet.Servlet; 12 13 @Configuration 14 public class HystrixConfig { 15 16 /** 17 * A {@link ServletContextInitializer} to register {@link Servlet}s in a Servlet 3.0+ container. 18 */ 19 @Bean 20 public ServletRegistrationBean hystrixMetricsStreamServlet() { 21 return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream"); 22 } 23 24 /** 25 * AspectJ aspect to process methods which annotated with {@link HystrixCommand} annotation. 26 * 27 * {@link HystrixCommand} annotation used to specify some methods which should be processes as hystrix commands. 28 */ 29 @Bean 30 public HystrixCommandAspect hystrixCommandAspect() { 31 return new HystrixCommandAspect(); 32 } 33 34 }
4. hystrix-dashboard
http://localhost:7979/hystrix-dashboard/
参考
https://github.com/Netflix/Hystrix/wiki/Configuration
https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-metrics-event-stream
https://github.com/Netflix-Skunkworks/hystrix-dashboard