资讯专栏INFORMATION COLUMN

Sentinel: 使用注解限流

Kross / 493人阅读

摘要:要使用注解来保护资源需要引入下面的依赖引入之后我们需要配置切面让其生效,因为是通过切面来实现的,我这边以中使用进行配置示列然后在需要限制的方法上加注解即可错误发生在表示资源名,必填项处理的方法名,可选项。

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

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


    com.alibaba.csp
    sentinel-annotation-aspectj
    1.4.1

引入之后我们需要配置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 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.ucloud.cn/yun/77463.html

相关文章

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

    摘要:实现熔断降级注解除了可以用来做限流控制之外,还能实现与类似的熔断降级策略。函数签名要求返回值类型必须与原函数返回值类型一致方法参数列表需要为空,或者可以额外多一个类型的参数用于接收对应的异常。若未配置和,则被限流降级时会将直接抛出。 在之前的《使用Sentinel实现接口限流》一文中,我们仅依靠引入Spring Cloud Alibaba对Sentinel的整合封装spring-clo...

    Lionad-Morotar 评论0 收藏0
  • [Spring-Cloud-Alibaba] Sentinel 整合RestTemplate &am

    摘要:开发阶段很有意义。源码整合配置文件中添加来开启编写类,实现默认用户远程调用被限流降级,默认用户应用定义可以拿到异常信息无法拿到异常信息若初启动应用,设置流控规则,结果展示如下默认用户源码 Sentinel API Github : WIKI Sphu (指明要保护的资源名称) Tracer (指明调用来源,异常统计接口) ContextUtil(标示进入调用链入口) 流控规则(针...

    libin19890520 评论0 收藏0
  • 阿里Sentinel支持Spring Cloud Gateway啦

    摘要:应对突发请求时额外允许的请求数目。匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。和为后续参数匹配特性预留,目前未实现。 1. 前言 4月25号,Sentinel 1.6.0 正式发布,带来 Spring Cloud Gateway 支持、控制台登录功能、改进的热点限流和注解 fallback 等多项新特性,该出手时就出手,紧跟时代潮流,昨天刚发布,今天我就要给大家分...

    chengtao1633 评论0 收藏0
  • 分布式熔断降级平台aegis

    摘要:现状分布式场景中。因此要对在原服务不可用时进行熔断降级处理。分析熔断降级可以服务端限流网关限流客户端限流。它提供两种资源隔离的模式信号量隔离和线程池隔离。支持流控熔断降级系统保护等。它支持并发数的流量控制也支持熔断降级。 现状 分布式场景中。若服务不稳定,会导致调用方服务也不可用,从而造成雪崩效应。因此要对在原服务不可用时进行熔断降级处理。 分析 熔断降级可以服务端限流、网关限流、客户...

    ixlei 评论0 收藏0
  • Spring Cloud Alibaba基础教程:Sentinel使用Apollo存储规则

    摘要:上一篇我们介绍了如何通过的配置功能来存储限流规则。第六步启动应用。深入思考在使用存储规则配置的时候与存储一样,对于控制台这些数据是只读的,也就是说控制台中修改规则仅存在于服务的内存中,不会修改中的配置值,重启后恢复原来的值。 上一篇我们介绍了如何通过Nacos的配置功能来存储限流规则。Apollo是国内用户非常多的配置中心,所以,今天我们继续说说Spring Cloud Alibaba...

    Airmusic 评论0 收藏0

发表评论

0条评论

Kross

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<