Sentinel源码—7.参数限流和注解的实现二

大纲

1.参数限流的原理和源码

2.@SentinelResource注解的使用和实现

2.@SentinelResource注解的使用和实现

(1)@SentinelResource注解的使用

(2)@SentinelResource注解和实现

(1)@SentinelResource注解的使用

一.引入Sentinel Spring Boot Starter依赖

复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

二.为方法添加@SentinelResource注解

下面的代码为sayHello()方法添加了@SentinelResource注解,并指定了资源名称为sayHello以及熔断降级时的回调方法fallback()。这样在请求sayHello()方法后,就可以在Sentinel Dashboard上看到此资源,然后就可以针对此资源进行一系列的规则配置了。

复制代码
@Service
public class MyService {
    @SentinelResource(value = "sayHello", fallback = "fallback")
    public String sayHello(String name) {
        return "Hello, " + name;
    }

    public String fallback(String name, Throwable throwable) {
        return "Fallback: " + name + ", reason: " + throwable.getMessage();
    }
}

(2)@SentinelResource注解和实现

利用Spring AOP拦截@SentinelResource注解,最后调用SphU.entry()方法来进行处理。

复制代码
//Aspect for methods with {@link SentinelResource} annotation.
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
    //SentinelResource注解
    @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();
        int resourceType = annotation.resourceType();
        //创建一个Entry对象,通过SphU.entry(resourceName)将当前方法纳入Sentinel的保护体系
        //如果当前资源的调用未触发任何Sentinel规则,则正常执行被拦截的方法,否则将执行对应的限流、熔断降级等处理逻辑
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
            return pjp.proceed();
        } catch (BlockException ex) {
            //发生异常时,通过反射执行在注解中设置的降级方法
            return handleBlockException(pjp, annotation, ex);
        } catch (Throwable ex) {
            Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
            //The ignore list will be checked first.
            if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
                throw ex;
            }
            if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
                traceException(ex);
                return handleFallback(pjp, annotation, ex);
            }
            //No fallback function can handle the exception, so throw it out.
            throw ex;
        } finally {
            if (entry != null) {
                entry.exit(1, pjp.getArgs());
            }
        }  
    }
}

//Some common functions for Sentinel annotation aspect.
public abstract class AbstractSentinelAspectSupport {
    ...
    protected Object handleBlockException(ProceedingJoinPoint pjp, SentinelResource annotation, BlockException ex) throws Throwable {
        //Execute block handler if configured.
        Method blockHandlerMethod = extractBlockHandlerMethod(pjp, annotation.blockHandler(), annotation.blockHandlerClass());
        if (blockHandlerMethod != null) {
            Object[] originArgs = pjp.getArgs();
            //Construct args.
            Object[] args = Arrays.copyOf(originArgs, originArgs.length + 1);
            args[args.length - 1] = ex;
            return invoke(pjp, blockHandlerMethod, args);
        }
        //If no block handler is present, then go to fallback.
        return handleFallback(pjp, annotation, ex);
    }

    private Object invoke(ProceedingJoinPoint pjp, Method method, Object[] args) throws Throwable {
        try {
            if (!method.isAccessible()) {
                makeAccessible(method);
            }
            if (isStatic(method)) {
                return method.invoke(null, args);
            }
            return method.invoke(pjp.getTarget(), args);
        } catch (InvocationTargetException e) {
            //throw the actual exception
            throw e.getTargetException();
        }
    }
    ...
}
相关推荐
.生产的驴23 分钟前
Maven 公司内部私服中央仓库搭建 局域网仓库 资源共享 依赖包构建共享
java·maven
Auc2424 分钟前
OJ判题系统第6期之判题逻辑开发——设计思路、实现步骤、代码实现(策略模式)
java·开发语言·docker·容器·策略模式
快乐肚皮32 分钟前
深入解析Docker:核心架构与最佳实践
java·运维·docker·容器
zhou18538 分钟前
MySQL保姆级安装教程(附资源包+5分钟极速配置+环境变量调试技巧)
java·python·mysql·php
小雅痞1 小时前
[Java][Leetcode middle] 55. 跳跃游戏
java·leetcode
com未来1 小时前
使用 NSSM 安装 Tomcat 11.0.6 为 Windows 服务
java·windows·tomcat
TDengine (老段)1 小时前
基于 TSBS 标准数据集下 TimescaleDB、InfluxDB 与 TDengine 性能对比测试报告
java·大数据·开发语言·数据库·时序数据库·tdengine·iotdb
养军博客1 小时前
spring boot3.0自定义校验注解:文章状态校验示例
java·前端·spring boot
lgily-12251 小时前
常用的设计模式详解
java·后端·python·设计模式
IT成长史1 小时前
deepseek梳理java高级开发工程师微服务面试题
java·微服务