当前位置: 首页 > news >正文

聊聊sentinel的AuthoritySlot

为什么80%的码农都做不了架构师?>>>   hot3.png

本文主要研究一下sentinel的AuthoritySlot

AuthoritySlot

com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot.java

public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args)
        throws Throwable {
        AuthorityRuleManager.checkAuthority(resourceWrapper, context, node, count);
        fireEntry(context, resourceWrapper, node, count, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }
}
  • 这里执行AuthorityRuleManager.checkAuthority进行校验

AuthorityRuleManager

com/alibaba/csp/sentinel/slots/block/authority/AuthorityRuleManager.java

public class AuthorityRuleManager {

    private static Map<String, List<AuthorityRule>> authorityRules
        = new ConcurrentHashMap<String, List<AuthorityRule>>();

    final static RulePropertyListener listener = new RulePropertyListener();

    private static SentinelProperty<List<AuthorityRule>> currentProperty
        = new DynamicSentinelProperty<List<AuthorityRule>>();

    static {
        currentProperty.addListener(listener);
    }

    public static void register2Property(SentinelProperty<List<AuthorityRule>> property) {
        synchronized (listener) {
            if (currentProperty != null) {
                currentProperty.removeListener(listener);
            }
            property.addListener(listener);
            currentProperty = property;
        }
    }

    /**
     * Load the authority rules to memory.
     *
     * @param rules list of authority rules
     */
    public static void loadRules(List<AuthorityRule> rules) {
        currentProperty.updateValue(rules);
    }

    public static void checkAuthority(ResourceWrapper resource, Context context, DefaultNode node, int count)
        throws BlockException {
        if (authorityRules == null) {
            return;
        }

        List<AuthorityRule> rules = authorityRules.get(resource.getName());
        if (rules == null) {
            return;
        }

        for (AuthorityRule rule : rules) {
            if (!rule.passCheck(context, node, count)) {
                throw new AuthorityException(context.getOrigin());
            }
        }
    }

    public static boolean hasConfig(String resource) {
        return authorityRules.containsKey(resource);
    }

    /**
     * Get a copy of the rules.
     *
     * @return a new copy of the rules.
     */
    public static List<AuthorityRule> getRules() {
        List<AuthorityRule> rules = new ArrayList<AuthorityRule>();
        if (authorityRules == null) {
            return rules;
        }
        for (Map.Entry<String, List<AuthorityRule>> entry : authorityRules.entrySet()) {
            rules.addAll(entry.getValue());
        }
        return rules;
    }

    private static class RulePropertyListener implements PropertyListener<List<AuthorityRule>> {

        @Override
        public void configUpdate(List<AuthorityRule> conf) {
            Map<String, List<AuthorityRule>> rules = loadAuthorityConf(conf);

            authorityRules.clear();
            if (rules != null) {
                authorityRules.putAll(rules);
            }
            RecordLog.info("[AuthorityRuleManager] Authority rules received: " + authorityRules);
        }

        private Map<String, List<AuthorityRule>> loadAuthorityConf(List<AuthorityRule> list) {
            if (list == null) {
                return null;
            }
            Map<String, List<AuthorityRule>> newRuleMap = new ConcurrentHashMap<String, List<AuthorityRule>>();
            for (AuthorityRule rule : list) {
                if (StringUtil.isBlank(rule.getLimitApp())) {
                    rule.setLimitApp(FlowRule.LIMIT_APP_DEFAULT);
                }

                String identity = rule.getResource();
                List<AuthorityRule> ruleM = newRuleMap.get(identity);
                // putIfAbsent
                if (ruleM == null) {
                    ruleM = new ArrayList<AuthorityRule>();
                    ruleM.add(rule);
                    newRuleMap.put(identity, ruleM);
                } else {
                    // One resource should only have at most one authority rule, so just ignore redundant rules.
                    RecordLog.warn("[AuthorityRuleManager] Ignoring redundant rule: " + rule.toString());
                }
            }

            return newRuleMap;
        }

        @Override
        public void configLoad(List<AuthorityRule> value) {
            Map<String, List<AuthorityRule>> rules = loadAuthorityConf(value);

            authorityRules.clear();
            if (rules != null) {
                authorityRules.putAll(rules);
            }
            RecordLog.info("[AuthorityRuleManager] Load authority rules: " + authorityRules);
        }
    }

}
  • checkAuthority方法从authorityRules中获取对应资源的规则,之后挨个进行rule.passCheck校验

AuthorityRule

com/alibaba/csp/sentinel/slots/block/authority/AuthorityRule.java

public class AuthorityRule extends AbstractRule {

    /**
     * Mode: 0 for whitelist; 1 for blacklist.
     */
    private int strategy = RuleConstant.AUTHORITY_WHITE;

    public int getStrategy() {
        return strategy;
    }

    public void setStrategy(int strategy) {
        this.strategy = strategy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (!(o instanceof AuthorityRule)) { return false; }
        if (!super.equals(o)) { return false; }

        AuthorityRule rule = (AuthorityRule)o;

        return strategy == rule.strategy;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + strategy;
        return result;
    }

    @Override
    public boolean passCheck(Context context, DefaultNode node, int count, Object... args) {
        String requester = context.getOrigin();

        // Empty origin or empty limitApp will pass.
        if (StringUtil.isEmpty(requester) || StringUtil.isEmpty(this.getLimitApp())) {
            return true;
        }

        // Do exact match with origin name.
        int pos = this.getLimitApp().indexOf(requester);
        boolean contain = pos > -1;

        if (contain) {
            boolean exactlyMatch = false;
            String[] appArray = this.getLimitApp().split(",");
            for (String app : appArray) {
                if (requester.equals(app)) {
                    exactlyMatch = true;
                    break;
                }
            }

            contain = exactlyMatch;
        }

        if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {
            return false;
        }

        if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {
            return false;
        }

        return true;
    }

    @Override
    public String toString() {
        return "AuthorityRule{" +
            "resource=" + getResource() +
            ", limitApp=" + getLimitApp() +
            ", strategy=" + strategy +
            "} ";
    }
}
  • passCheck方法通过context的origin跟limitApp进行匹配

CommonFilter

com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.java

public class CommonFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest sRequest = (HttpServletRequest)request;
        Entry entry = null;

        try {
            String target = FilterUtil.filterTarget(sRequest);
            target = WebCallbackManager.getUrlCleaner().clean(target);

            ContextUtil.enter(target);
            entry = SphU.entry(target, EntryType.IN);

            chain.doFilter(request, response);
        } catch (BlockException e) {
            HttpServletResponse sResponse = (HttpServletResponse)response;
            WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse);
        } catch (IOException e2) {
            Tracer.trace(e2);
            throw e2;
        } catch (ServletException e3) {
            Tracer.trace(e3);
            throw e3;
        } catch (RuntimeException e4) {
            Tracer.trace(e4);
            throw e4;
        } finally {
            if (entry != null) {
                entry.exit();
            }
            ContextUtil.exit();
        }
    }

    @Override
    public void destroy() {

    }
}
  • 目前基于servlet的CommonFilter,在调用ContextUtil.enter(target)的时候,并没有指定origin,目前默认为""

小结

AuthoritySlot主要用来做黑白名单的匹配,现在还不是很完善,origin在CommonFilter进入entry时没有指定。

doc

  • AuthoritySlot

转载于:https://my.oschina.net/go4it/blog/1933315

相关文章:

  • element.style覆盖了我的样式!!
  • 折腾一天终于尝到了 signalr core了
  • IP地址便捷修改器 V3.5 绿色版
  • 解决子级用css float浮动 而父级div没高度不能自适应高度
  • 滴滴公布自查进展:免去黄洁莉顺风车事业部总经理职务
  • 浅谈HTML5单页面架构(一)——requirejs + angular + angular-route
  • DHCP的配置文档
  • 53次课( NFS介绍、 NFS服务端安装配置、NFS配置选项)
  • 列出对像属性,for(var i in obj)[转]
  • mongodb嵌套文档结构设计
  • IO流之转换流
  • Enerprise Solution Main 启动方法源代码
  • position的static、relative、absolute、fixed、inherit
  • 内部和外部排序排序
  • python遍历
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • Apache Zeppelin在Apache Trafodion上的可视化
  • js 实现textarea输入字数提示
  • JS实现简单的MVC模式开发小游戏
  • node.js
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • SpringBoot几种定时任务的实现方式
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Vue.js-Day01
  • Vue2.0 实现互斥
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 使用Gradle第一次构建Java程序
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 运行时添加log4j2的appender
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • # centos7下FFmpeg环境部署记录
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #DBA杂记1
  • #预处理和函数的对比以及条件编译
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (八十八)VFL语言初步 - 实现布局
  • (第二周)效能测试
  • (二)springcloud实战之config配置中心
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (转)winform之ListView
  • ****Linux下Mysql的安装和配置
  • .NET Framework 4.6.2改进了WPF和安全性
  • .Net Redis的秒杀Dome和异步执行
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [.net]官方水晶报表的使用以演示下载
  • []FET-430SIM508 研究日志 11.3.31
  • []常用AT命令解释()
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [BT]BUUCTF刷题第4天(3.22)
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析