本文主要研究一下sentinel的AuthoritySlotjava
com/alibaba/csp/sentinel/slots/block/authority/AuthoritySlot.javanode
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); } }
com/alibaba/csp/sentinel/slots/block/authority/AuthorityRuleManager.javagit
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); } } }
com/alibaba/csp/sentinel/slots/block/authority/AuthorityRule.javagithub
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 + "} "; } }
com/alibaba/csp/sentinel/adapter/servlet/CommonFilter.javaapp
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() { } }
AuthoritySlot主要用來作黑白名單的匹配,如今還不是很完善,origin在CommonFilter進入entry時沒有指定。ide