创建熔断注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyHystrixCommand {
long timeout() default 1000; // 超时时间默认为 1000 毫秒(一秒)
String callBack() default ""; // 回调方法
}
创建 AOP 类
@Aspect
@Component
public class MyHystrixAop {
// 创建一个固定大小的线程池
private ExecutorService executorService = Executors.newFixedThreadPool(10);
// 切入点
@Pointcut("@annotation(MyHystrixCommand)")
public void pointCut(){}
// 拦截加了 @MyHystrixCommand 的注解
@Around("pointCut() && @annotation(myHystrixCommand)")
public Object doPointCut(ProceedingJoinPoint joinPoint,MyHystrixCommand myHystrixCommand) throws InterruptedException, ExecutionException, TimeoutException {
// 获取目标方法返回值
Future future = executorService.submit(()->{
// 调用目标方法
try {
return joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
});
Object result = null;
try {
// 在自己设置的指定时间内获取目标方法返回值
result = future.get(myHystrixCommand.timeout(), TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException |TimeoutException e) {
e.printStackTrace();
// 出错结束请求
future.cancel(true);
if(StringUtils.isEmpty(myHystrixCommand.callBack())){
throw e;
}
}
if(result == null){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// 获取目标方法
Method method = methodSignature.getMethod();
// 获取方法参数
Class<?>[] parameterTypes = method.getParameterTypes();
// 获取熔断方法
Method m = null;
try {
m = joinPoint.getTarget().getClass().getMethod(myHystrixCommand.callBack(), parameterTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 调用熔断方法
try {
return m.invoke(joinPoint.getTarget(),joinPoint.getArgs());
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
创建 Controller 类
@RestController
@RequestMapping("/hystrix/test")
public class MyHystrixController {
// 熔断注解 设置超时时间
@MyHystrixCommand(timeout = 2000,callBack = "callBack")
@RequestMapping("/req")
public String getUserInfoById(String userId){
return "请求成功";
}
/**
* 熔断方法
* @param userId
* @return
*/
public String callBack(String userId){
return "请求熔断了...";
}
}
正常测试,超时时间是 2000 毫秒
image.png
我们让 AOP 类中请求目标方法休息 3000 毫秒试试看
image.png
结果请求超时了,调用了熔断方法
image.png
网友评论