一穿铆、引子
上一節(jié)分析了SystemSlot是如何進(jìn)行系統(tǒng)規(guī)則的檢查的您单,檢查了系統(tǒng)的qps,rt荞雏,thead虐秦,負(fù)載。
接下來繼續(xù)分析Slot鏈的下一個插槽AuthoritySlot(黑白名單控制)凤优。
二悦陋、黑白名單控制
很多時候,我們需要根據(jù)調(diào)用方來限制資源是否通過筑辨,這時候可以使用 Sentinel 的黑白名單控制的功能叨恨。黑白名單根據(jù)資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位于白名單內(nèi)時才可通過挖垛;若配置黑名單則請求來源位于黑名單時不通過,其余的請求通過秉颗。
調(diào)用方信息通過
ContextUtil.enter(resourceName, origin)
方法中的origin
參數(shù)傳入痢毒。
規(guī)則配置
黑白名單規(guī)則(AuthorityRule)非常簡單,主要有以下配置項(xiàng):
- resource:資源名蚕甥,即限流規(guī)則的作用對象
- limitApp:對應(yīng)的黑名單/白名單哪替,不同 origin 用 , 分隔,如 appA,appB
- strategy:限制模式菇怀,AUTHORITY_WHITE 為白名單模式凭舶,AUTHORITY_BLACK 為黑名單模式晌块,默認(rèn)為白名單模式
三、源碼分析
1帅霜、AuthoritySlot
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args)
throws Throwable {
checkBlackWhiteAuthority(resourceWrapper, context);
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
@Override
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
fireExit(context, resourceWrapper, count, args);
}
void checkBlackWhiteAuthority(ResourceWrapper resource, Context context) throws AuthorityException {
Map<String, List<AuthorityRule>> authorityRules = AuthorityRuleManager.getAuthorityRules();
if (authorityRules == null) {
return;
}
List<AuthorityRule> rules = authorityRules.get(resource.getName());
if (rules == null) {
return;
}
for (AuthorityRule rule : rules) {
if (!AuthorityRuleChecker.passCheck(rule, context)) {
throw new AuthorityException(context.getOrigin());
}
}
}
}
1.在checkBlackWhiteAuthority方法中匆背,首先通過AuthorityRuleManager獲取得到所有的規(guī)則,AuthorityRuleManager是授權(quán)規(guī)則的管理類身冀,可以動態(tài)獲取從dashboard增加的規(guī)則钝尸。
2.根據(jù)資源名獲取該資源對應(yīng)的規(guī)則
3.調(diào)用AuthorityRuleChecker的pass方法進(jìn)行授權(quán)規(guī)則的校驗(yàn),如果返回false說明被攔截了搂根,則拋出一個異常珍促。
2、AuthorityRuleChecker
AuthorityRuleChecker就是授權(quán)規(guī)則檢測的類剩愧,該類是個final修飾的猪叙,下面具體分析。
final class AuthorityRuleChecker {
static boolean passCheck(AuthorityRule rule, Context context) {
String requester = context.getOrigin();
// Empty origin or empty limitApp will pass.
if (StringUtil.isEmpty(requester) || StringUtil.isEmpty(rule.getLimitApp())) {
return true;
}
// Do exact match with origin name.
int pos = rule.getLimitApp().indexOf(requester);
boolean contain = pos > -1;
if (contain) {
boolean exactlyMatch = false;
String[] appArray = rule.getLimitApp().split(",");
for (String app : appArray) {
if (requester.equals(app)) {
exactlyMatch = true;
break;
}
}
contain = exactlyMatch;
}
int strategy = rule.getStrategy();
if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {
return false;
}
if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {
return false;
}
return true;
}
private AuthorityRuleChecker() {}
}
1.首先通過context.getOrigin()獲取請求源仁卷,并判斷requester和limitApp是否為空穴翩。
2.先用requester做精確匹配是否在字符串limitApp中,對于授權(quán)規(guī)則limitApp可以有多個五督,用逗號(,)分隔藏否。
3.然后再判斷requester是否是配置limitApp中的其中的一個,這里為什么會有第二步充包,因?yàn)槿绻鹟imitApp字符串都不包含requester的話副签,requester肯定不在limitApp中,可以理解第二步是一個預(yù)判斷基矮。
4.獲取rule.getStrategy()的策略淆储,這里的策略有兩個。
public static final int AUTHORITY_WHITE = 0; //白名單
public static final int AUTHORITY_BLACK = 1; //黑名單
5.如果配置的策略是黑名單且requester在配置在limitApp中家浇,則請求攔截本砰。
6.如果配置的策略是白名單且requester在配置不在limitApp中,則請求攔截钢悲。
7.否則請求不攔截点额。
四、我的總結(jié)
1莺琳、AuthoritySlot插槽是整個插槽鏈規(guī)則校驗(yàn)的第二個还棱,用于授權(quán)規(guī)則設(shè)置的校驗(yàn)。
2惭等、授權(quán)規(guī)則有三個配置項(xiàng):resource(資源名)珍手,limitApp(限制來源),strategy(策略)。
3琳要、limitApp可以有多個寡具,用逗號分隔。strategy有兩個策略稚补,白名單童叠、黑名單。
4孔厉、系統(tǒng)規(guī)則限制可以用一句話就說明:如果配置的策略是黑名單且requester在配置在limitApp中拯钻,則請求攔截;如果配置的策略是白名單且requester在配置不在limitApp中撰豺,則請求攔截粪般;否則請求不攔截。