Sentinel学习(五) —— 控制台使用和源码

本文详细介绍了Sentinel控制台的启动、接入、流控规则、降级规则、热点规则、系统规则和授权规则,以及相关源码解析。通过Sentinel控制台,可以对应用的规则进行管理和监控。流控规则包括直接、关联和链路模式,降级规则依据RT、异常比例和异常数。热点规则用于限制热点资源访问,系统规则关注系统负载、RT和线程数。源码分析部分主要涉及不同规则的判断逻辑和处理过程。
摘要由CSDN通过智能技术生成

通过 sentinel 的控制台,我们可以对规则进行查询和修改,也可以查看到实时监控,机器列表等信息,所以我们需要对 sentinel 的控制台做个完整的了解。

启动控制台

从github上下载源码后,启动sentinel-dashboard模块。默认地址是8080。用户名和密码配置到了application.properties中,可以自行修改,默认用户名和密码都是 sentinel
在这里插入图片描述
可以看到当前控制台中没有任何的应用,因为还没有应用接入。

接入控制台

要想在控制台中操作我们的应用,除了需要部署一个控制台的服务外,还需要将我们的应用接入到控制台中去。

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

增加配置参数:控制台地址。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

控制台使用懒加载,在第一次访问的时候才会开始进行初始化,并向控制台发送心跳和客户端规则等信息。
在这里插入图片描述
下面让我们对控制台的功能做具体的介绍。

流控规则

在簇点链路中可以配置流控规则,我们看下每个选项的含义。
在这里插入图片描述

  • 资源名:默认使用请求路径,也可以修改成其他名称。
  • 针对来源:可以对服务的调用来源进行限流。default为默认,会限流所有来源,也可以设置成其他服务名。
  • 阀值类型:分为QPS和线程数,指的是到达限流的判断条件。
  • 是否集群:设置单机还是集群限流,这个之后再讲解。
  • 流控模式:
    • 直接:指的是限流的目标就是当前的资源。
    • 关联:需要填写关联资源。当关联资源的访问达到限流阀值,就会限制当前资源的访问。这是对关联资源的一种保护策略。
    • 链路:这个是对来源更细粒度的配置。需要配置入口资源,也就是说从某个请求URL的入口进入才会进行流控判断。比如:/test-a 和 /test-b 都调用 /common这个资源。如果入口资源配置成 /test-a,那么 /test-b 不会进行流量控制。
  • 流控效果:
    • 快速失败:如果流控就抛出异常。
    • Warm Up:先进行预热,根据codeFactor(默认是3)的值,从阀值/codeFactor,经过预热时长(秒)才到达设置的QPS阀值。
    • 排队等待:匀速排队,让请求以均匀的速度通过,阀值类型必须设置成QPS,否则无效。需要设置超时时间,如果超出超时时间,请求才会被丢弃。
源码解析

流控是用FlowSlot进行的判断。它也是责任链上的其中一个节点。我们知道这些节点的统一处理入口都是 entry方法。

FlowSlot#entry

public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                  boolean prioritized, Object... args) throws Throwable {
   
    checkFlow(resourceWrapper, context, node, count, prioritized);

    fireEntry(context, resourceWrapper, node, count, prioritized, args);
}

void checkFlow(ResourceWrapper resource, Context context, DefaultNode node, int count, boolean prioritized)
    throws BlockException {
   
    checker.checkFlow(ruleProvider, resource, context, node, count, prioritized);
}

FlowSlot在实例化的时候会实例化一个FlowRuleChecker实例作为checker。在checkFlow方法里面会继续调用FlowRuleChecker的checkFlow方法,其中ruleProvider实例是用来根据根据resource来从flowRules中获取相应的FlowRule。

我们进入到FlowRuleChecker的checkFlow方法中

FlowRuleChecker#checkFlow

public void checkFlow(Function<String, Collection<FlowRule>> ruleProvider, ResourceWrapper resource,
                      Context context, DefaultNode node, int count, boolean prioritized) throws BlockException {
   
    if (ruleProvider == null || resource == null) {
   
        return;
    }
    //返回FlowRuleManager里面注册的所有规则
    Collection<FlowRule> rules = ruleProvider.apply(resource.getName());
    if (rules != null) {
   
        for (FlowRule rule : rules) {
   
            //如果当前的请求不能通过,那么就抛出FlowException异常
            if (!canPassCheck(rule, context, node, count, prioritized)) {
   
                throw new FlowException(rule.getLimitApp(), rule);
            }
        }
    }
}

这里是调用ruleProvider来获取所有FlowRule,然后遍历rule集合通过canPassCheck方法来进行过滤,如果不符合条件则会抛出FlowException异常。

我们跟进去直接来到passLocalCheck方法:

private static boolean passLocalCheck(FlowRule rule, Context context, DefaultNode node, int acquireCount,
                                      boolean prioritized) {
   
    //节点选择
    Node selectedNode = selectNodeByRequesterAndStrategy(rule, context, node);
    if (selectedNode == null) {
   
        return true;
    }
    //根据设置的规则来拦截
    return rule.getRater().canPass(selectedNode, acquireCount, prioritized);
}

这个方法里面会选择好相应的节点后调用rater的canPass方法来判断是否需要阻塞。

Rater有四个,分别是:DefaultController、RateLimiterController、WarmUpController、WarmUpRateLimiterController。它们是什么时候创建的呢?主要是调用了下面的这个方法。

FlowRuleUtil#generateRater

private static TrafficShapingController generateRater(/*@Valid*/ FlowRule rule) {
   
    if (rule.getGrade() == RuleConstant.FLOW_GRADE_QPS) {
   
        switch (rule.getControlBehavior()) {
   
            case RuleConstant.CONTROL_BEHAVIOR_WARM_UP:
                //warmUpPeriodSec默认是10 
                return new WarmUpController(rule.getCount(), rule.getWarmUpPeriodSec(),
                    ColdFactorProperty.coldFactor);
            case RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER:
                //rule.getMaxQueueingTimeMs()默认是500
                return new RateLimiterController(rule.getMaxQueueingTimeMs(), rule.getCount());
            case RuleConstant.CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER:
                return new WarmUpRateLimiterController(rule.getCount(), rule.getWarmUpPeriodSec(),
                    rule.getMaxQueueingTimeMs(), ColdFactorProperty.coldFactor);
            case RuleConstant.CONTROL_BEHAVIOR_DEFAULT:
            default:
                // Default mode or unknown mode: default traffic shaping controller (fast-reject).
        }
    }
    return new DefaultController(rule.getCount(), rule.getGrade());
}

这个方法里面如果设置的是按QPS的方式来限流的话,可以设置一个ControlBehavior属性,用来做流量控制分别是:直接拒绝、Warm Up、匀速排队。

RateLimiterController匀速排队

它的中心思想是,以固定的间隔时间让请求通过。当请求到来的时候,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过;否则,计算当前请求的预期通过时间,如果该请求的预期通过时间小于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过(排队等待处理);若预期的通过时间超出最大排队时长,则直接拒接这个请求。

这种方式适合用于请求以突刺状来到,这个时候我们不希望一下子把所有的请求都通过,这样可能会把系统压垮;同时我们也期待系统以稳定的速度,逐步处理这些请求,以起到“削峰填谷”的效果,而不是拒绝所有请求。

要想使用这个策略需要在实例化FlowRule的时候设置rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)这样的一句代码。

在实例化Rater的时候会调用FlowRuleUtil#generateRater创建一个实例:

new RateLimiterController(rule.getMaxQueueingTimeMs(), rule.getCount());

MaxQueueingTimeMs默认是500 ,Count在我们这个例子中传入的是20。

我们看一下具体的canPass方法是怎么实现限流的:

public boolean canPass(Node node, int acquireCount, boolean prioritized) {
   
    // Pass when acquire count is less or equal than 0.
    if (acquireCount <= 0) {
   
        return true;
    }
    // Reject when count is less or equal than 0.
    // Otherwise,the costTime will be max of long and waitTime will overflow in some cases.
    if (count <= 0) {
   
        return false;
    }

    long currentTime = TimeUtil.currentTimeMillis();
    //两个请求预期通过的时间,也就是说把请求平均分配到1秒上
    // Calculate the interval between every two requests.
    long costTime = Math.round(1.0 * (acquireCount) / count * 1000);

    //latestPassedTime代表的是上一次调用请求的时间
    // Expected pass time of this request.
    long expectedTime = costTime + latestPassedTime.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值