Sentinel: 使用注解限流

在前面我们对Sentinel做了一个详细的介绍,可以手动的通过Sentinel提供的SphU类来保护资源。这种做法不好的地方在于每个需要限制的地方都得写代码,从 0.1.1 版本开始,Sentinel 提供了 @SentinelResource 注解的方式,非常方便。

要使用注解来保护资源需要引入下面的Maven依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.4.1</version>
</dependency>

引入之后我们需要配置SentinelResourceAspect切面让其生效,因为是通过SentinelResourceAspect切面来实现的,我这边以Spring Boot中使用进行配置示列:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;

@Configuration
public class AopConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

}

然后在需要限制的方法上加SentinelResource注解即可:

@SentinelResource(value = "get", blockHandler = "exceptionHandler")
@Override
public String get(String id) {
   return "http://cxytiandi.com";
}

public String exceptionHandler(String id, BlockException e) {
   e.printStackTrace();
   return "错误发生在" + id;
}

SentinelResource:value

表示资源名,必填项

SentinelResource:blockHandler

处理 BlockException 的方法名,可选项。若未配置,则将 BlockException 直接抛出。

  • blockHandler 函数访问范围需要是 public
  • 返回类型需要与原方法相匹配
  • 参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException
  • blockHandler 函数默认需要和原方法在同一个类中

如果你不想让异常处理方法跟业务方法在同一个类中,可以使用 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

业务方法:

@SentinelResource(value = "get2", blockHandler = "handleException", blockHandlerClass = { ExceptionUtil.class })
@Override
public String get2() {
    return "http://cxytiandi.com";
}

异常处理类:

import com.alibaba.csp.sentinel.slots.block.BlockException;

public final class ExceptionUtil {

    public static String handleException(BlockException ex) {
        System.err.println("错误发生: " + ex.getClass().getCanonicalName());
        return "error";
    }

}

如何测试?

我们可以在Spring Boot的启动类中定义规则,然后快速访问接口,就可以看出效果啦,或者用压力测试工具ab等。

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        initFlowRules();
        SpringApplication.run(App.class, args);
    }

    private static void initFlowRules() {
        List<FlowRule> rules = new ArrayList<>();

        FlowRule rule = new FlowRule();
        rule.setResource("get");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(1);
        rules.add(rule);

        rule = new FlowRule();
        rule.setResource("get2");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(1);
        rules.add(rule);

        FlowRuleManager.loadRules(rules);
    }
}

源码分析

只需要配置了SentinelResourceAspect就可以使用注解,我们来简单的看下SentinelResourceAspect的源码

@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {

    @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
    public void sentinelResourceAnnotationPointcut() {
    }

    @Around("sentinelResourceAnnotationPointcut()")
    public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
        // 获取当前访问的方法
        Method originMethod = resolveMethod(pjp);
        // 获取方法上的SentinelResource注解
        SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
        if (annotation == null) {
            // Should not go through here.
            throw new IllegalStateException("Wrong state for SentinelResource annotation");
        }
        // 获取资源名
        String resourceName = getResourceName(annotation.value(), originMethod);
        EntryType entryType = annotation.entryType();
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, entryType, 1, pjp.getArgs());
            Object result = pjp.proceed();
            return result;
        } catch (BlockException ex) {
            // 处理被限制的异常,回调事先配置的异常处理方法
            return handleBlockException(pjp, annotation, ex);
        } catch (Throwable ex) {
            Tracer.trace(ex);
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }
}

上面是整个切面的代码,对所有加了SentinelResource注解的方法进去切入。细节代码在AbstractSentinelAspectSupport中,大家自己去看看。

欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

PS:目前星球中正在星主的带领下组队学习Sentinel,等你哦!

原文地址:https://www.cnblogs.com/yinjihuan/p/10516045.html

时间: 2024-08-30 11:25:30

Sentinel: 使用注解限流的相关文章

快速体验 Sentinel 集群限流功能,只需简单几步

? Pic by Alibaba Tech on Facebook 集群限流 可以限制某个资源调用在集群内的总 QPS,并且可以解决单机流量不均导致总的流控效果不佳的问题,是保障服务稳定性的利器. Sentinel 从 1.4.0 版本开始提供集群流控特性,但使用 Sentinel 集群限流需要对一系列的动态数据源进行相关配置,并且需要对开源控制台进行一些改造,有一定的使用成本.为了大家更好地理解集群流控并快速地使用,我们提供了云上版本的 Sentinel 集群限流控制台示例.只需要简单的几步即

Sentinel如何通过限流实现服务的高可用性

摘要: 在复杂的生产环境下可能部署着成千上万的服务实例,当流量持续不断地涌入,服务之间相互调用频率陡增时,会产生系统负载过高.网络延迟等一系列问题,从而导致某些服务不可用.如果不进行相应的流量控制,可能会导致级联故障,并影响到服务的可用性,因此如何对高流量进行合理控制,成为保障服务稳定性的关键. 在复杂的生产环境下可能部署着成千上万的服务实例,当流量持续不断地涌入,服务之间相互调用频率陡增时,会产生系统负载过高.网络延迟等一系列问题,从而导致某些服务不可用.如果不进行相应的流量控制,可能会导致级

spring cloud gateway整合sentinel作网关限流

说明: sentinel可以作为各微服务的限流,也可以作为gateway网关的限流组件. spring cloud gateway有限流功能,但此处用sentinel来作为替待. 说明:sentinel流控可以放在gateway网关端,也可以放在各微服务端. 1,以父工程为基础,创建子工程 2,添加pom依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>sprin

秒杀:注解限流

接口限流防刷 可以用缓存来实现,一分钟之内访问一次加1达到一定次数就拒绝 原文地址:https://www.cnblogs.com/xjatj/p/10327161.html

这个注解一次搞定限流与熔断降级:@SentinelResource

在之前的<使用Sentinel实现接口限流>一文中,我们仅依靠引入Spring Cloud Alibaba对Sentinel的整合封装spring-cloud-starter-alibaba-sentinel,就完成了对所有Spring MVC接口的限流控制.然而,在实际应用过程中,我们可能需要限流的层面不仅限于接口.可能对于某个方法的调用限流,对于某个外部资源的调用限流等都希望做到控制.呢么,这个时候我们就不得不手工定义需要限流的资源点,并配置相关的限流策略等内容了. 今天这篇我们就来一起学

Spring Cloud Alibaba | Sentinel: 服务限流高级篇

目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限流 3.1 背景 3.2 系统规则 3.3 原理 3.4 示例 4. 黑白名单控制 4.1 规则配置 4.2 示例 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架.而以下要介绍的正是作者最近两个月的真实项目实践过程,这中间被不少网络Demo示例级别水文误导过,为了以正视听特将实践过程加以总结,希望能够帮到有类似需要的朋友! 一.Sentinel概述 在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素.在并发流量比较高

更好用的集群限流功能,Sentinel 发布 v1.4.2

摘要: 感谢 Sentinel 社区的贡献者们 ? Sentinel 发布 v1.4.2 正式发布,该版本主要变更如下: 特性/功能改进 新增 Zuul 1.x 适配模块(sentinel-zuul-adapter),结合集群限流特性可以更好地在 API Gateway 发挥流控的作用 热点参数限流添加线程数模式支持 在 BlockException 中携带更多的信息(如触发的规则) 完善 Tracer,支持针对某个 Entry 或 Context 记录异常数目 优化 ClusterStateM

从构建分布式秒杀系统聊聊限流的多种实现

前言 俗话说的好,冰冻三尺非一日之寒,滴水穿石非一日之功,罗马也不是一天就建成的.两周前秒杀案例初步成型,分享到了中国最大的同×××友网站-码云.同时也收到了不少小伙伴的建议和投诉.我从不认为分布式.集群.秒杀这些就应该是大厂的专利,在互联网的今天无论什么时候都要时刻武装自己,只有这样,也许你的春天就在明天. 在开发秒杀系统案例的过程中,前面主要分享了队列.缓存.锁和分布式锁以及静态化等等.缓存的目的是为了提升系统访问速度和增强系统的处理能力:分布式锁解决了集群下数据的安全一致性问题:静态化无疑