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;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Hystrix是一个开源的熔断器框架,它能够帮助开发者有效地处理服务依赖的延迟和故障。熔断器的主要目的是在出现故障时提供一种优雅的降级机制,以避免整个系统的崩溃。 熔断和降级是Hystrix两个重要的概念。 熔断(Circuit Breaker)指的是在服务出现故障或错误率过高时,自动地切换到指定的备用服务或返回事先定义好的错误结果,起到保护系统免受故障传播的影响的作用。当服务不可用或响应时间过长时,熔断器会打开,拒绝后续请求的访问,并尝试通过执行降级逻辑来快速响应客户端。一旦后续请求不再出现故障,熔断器将会进入半开状态,允许少量的请求通过以检测服务是否恢复正常。 降级(Degradation)指的是在系统资源不足或者高访问量时,服务降级会关闭一些不重要的功能,以保证系统核心功能的可用性和稳定性。降级可以通过阻止非必要的调用、减少资源的消耗以及返回默认值或缓存结果来实现。降级需要提前定义好一些备用的逻辑,一旦系统资源紧张,就可以立即启用降级逻辑来保障系统的可用性。 总而言之,熔断和降级都是为了保护系统免受故障的影响。熔断主要是针对服务故障和错误率过高的情况,通过切换到备用服务或返回错误结果来保护系统。降级主要是在系统资源紧张或高访问量的情况下,关闭一些不重要的功能来保证核心功能的可用性和稳定性。两者都是通过提前定义备用逻辑来保障系统的正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值