Spring Cloud Hystrix 熔断和限流 使用和理解
1 可以直接使用Hystrix
maven 配置如下
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
threadPoolKey
fallbackMethod 失败回调方法
commandProperties
execution.isolation.strategy 隔离策略:当前使用thread,它在单独的线程上执行,并发请求受线程池中的线程数量的限制
execution.isolation.thread.timeoutInMillisecon 超过多久失败
具体参数解释可以查看这一篇好文:
https://blog.csdn.net/tongtong_use/article/details/78611225
简单代码如下:(启动类上 @EnableCircuitBreaker)
@HystrixCommand(
threadPoolKey = "test",
fallbackMethod = "sayHelloFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value="50")
})
@GetMapping(value = "/sayHello/{message}")
public String sayHello(@PathVariable(required = false) String message) {
Long p = Long.valueOf(message);
if (p > 5000l) {
p = 5000L;
}
try {
Thread.sleep(p);
} catch (InterruptedException e) {
}
return "Hello " + message;
}
public String sayHelloFallback(String message) {
return "fallback " + message;
}
2 自定义注解通过spring mvc拦截器的方式实现–熔断
如何实现拦截器 : https://www.cnblogs.com/zzb-yp/p/11512126.html
自定义注解实现hystrix中的超市调用fallback方法
A 实现一个方法的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyHystrixCommand {
/**
* 超时时间
* @return
*/
long value() default 5000L;
/**
* 时间单位
* @return
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
/**
* 补偿方法, 默认可以为空
* @return
*/
String fallback() default "";
}
B 拦截器具体实现
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(handler instanceof HandlerMethod) {
// 1 拿到参数,为后面反射调用
Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
String message = (String)pathVariables.get("message");
// 2 获取方法和实例
HandlerMethod handlerMethod = (HandlerMethod)handler;
Method method = handlerMethod.getMethod();
MyHystrixCommand hystrixCommand = method.getAnnotation(MyHystrixCommand.class);
if(hystrixCommand != null) {
Object bean = handlerMethod.getBean();
// 3 解析注解
Long value = hystrixCommand.value();
TimeUnit timeUnit = hystrixCommand.timeUnit();
String fallbackMethodName = hystrixCommand.fallback();
// 4 切换线程,反射调用已经拦截到的方法
Future<Object> future = executorService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
return method.invoke(bean, message);
}
});
Object returnValue = null;
// 6 等待注解中的时间,如果时间超过了,执行fallback方法构造返回数据返回
try {
returnValue = future.get(value, timeUnit);
} catch (TimeoutException e) {
Method fallbackMethod = bean.getClass().getMethod(fallbackMethodName, method.getParameterTypes());
}
response.getWriter().write(String.valueOf(returnValue));
return false;
}
}
return true;
}
C controller中控制访问
@GetMapping(value = "/say_hi/{message}")
@MyHystrixCommand(value = 50, timeUnit = TimeUnit.MILLISECONDS, fallback = "sayHiFallback")
public String sayHi(@PathVariable(required = false) String message) {
Long p = Long.valueOf(message);
if (p > 5000l) {
p = 5000L;
}
try {
Thread.sleep(p);
} catch (InterruptedException e) {
}
return "hi " + message;
}
public String sayHiFallback(String message) {
return "fallback " + message;
}
3 自定义注解 AOP方式实现–限流
Aop方法实现控制限流
A 构造Aop方法
// 为每个方法都初始化一个semaphore
private Map<Method, Semaphore> semaphoreMap = new ConcurrentHashMap<>();
@Around("@annotation(com.example.springcloud.demo.annotation.MyHystrixCommand2)")
public Object beforeMethodInvocation(ProceedingJoinPoint joinPoint) throws Throwable {
// 1 拿到经过有注解的方法
Signature signature = joinPoint.getSignature();
Object result = null;
if(signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
// 2 解析注解的参数
MyHystrixCommand2 hystrixCommand2 = method.getAnnotation(MyHystrixCommand2.class);
int permits = hystrixCommand2.value();
// 3 根据参数利用Semaphore做限流处理
Semaphore semaphore = initSemaphore(method, permits);
try {
semaphore.acquire();
result = joinPoint.proceed();
} finally {
semaphore.release();
}
}
return result;
}
public Semaphore initSemaphore(Method method, int permits) {
if(semaphoreMap.get(method) == null) {
semaphoreMap.put(method, new Semaphore(permits));
}
return semaphoreMap.get(method);
}
B controller方法调用(启动类加上@EnableAspectJAutoProxy)
@MyHystrixCommand2(10)
@GetMapping(value = "/goodbye/{message}")
public String sayGoodBye(@PathVariable(required = false) String message) {
return "goodbye" + message;
}
4 mvc修改为Aop
@Around("@annotation(com.example.springcloud.demo.annotation.MyHystrixCommand)")
public Object beforeMethodInvocation(ProceedingJoinPoint joinPoint) throws Throwable {
Signature signature = joinPoint.getSignature();
if(signature instanceof MethodSignature) {
// 1 拿到参数,为后面反射调用
// 2 获取方法和实例
MethodSignature methodSignature = (MethodSignature)signature;
Method method = methodSignature.getMethod();
Object bean = joinPoint.getTarget();
MyHystrixCommand hystrixCommand = method.getAnnotation(MyHystrixCommand.class);
if(hystrixCommand != null) {
// 3 解析注解
Long value = hystrixCommand.value();
TimeUnit timeUnit = hystrixCommand.timeUnit();
String fallbackMethodName = hystrixCommand.fallback();
Object[] parameters = joinPoint.getArgs();
// 4 切换线程,反射调用已经拦截到的方法
Future<Object> future = executorService.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
return joinPoint.proceed(parameters);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
});
Object returnValue = null;
// 6 等待注解中的时间,如果时间超过了,执行fallback方法构造返回数据返回
try {
returnValue = future.get(value, timeUnit);
} catch (TimeoutException e) {
Method fallbackMethod = bean.getClass().getMethod(fallbackMethodName, method.getParameterTypes());
returnValue = fallbackMethod.invoke(bean, parameters);
}
return returnValue;
}
}
return null;
}