Ali sentinel limiting learning

Disclaimer: This article is a blogger original article, please indicate the source. https://blog.csdn.net/u010597819/article/details/88927028

Article rocketmq demo is based on analysis of entrance

table of Contents

  1. Initialization flow control rules
  2. Flow Control
  3. Slot common node processing chain
  4. Flow control algorithm commonly used learning

Initialization flow control rules

  1. PullConsumerDemo.main start before consumption initialization message flow control rules _initFlowControlRule_
  2. Create a flow control rule: FlowRule
  3. Set resource resource, such as: GROUP_NAME group name and topic name TOPIC_NAME
  4. Set the flow control threshold count
  5. Set Flow Control Type Grade: FLOW_GRADE_THREAD thread-based flow control, FLOW_GRADE_QPS based flow control QPS
  6. Set to restrict the application of name limitApp: According to the source data limit, default is default on behalf of all applications
  7. Set the flow control behavior controlBehavior: CONTROL_BEHAVIOR_DEFAULT, CONTROL_BEHAVIOR_WARM_UP, CONTROL_BEHAVIOR_RATE_LIMITER (token bucket algorithm), CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER
  8. Set the maximum queue timeout maxQueueingTimeMs: If there are more requests come in, they will be placed in a queue waiting for the queue waiting for a timeout, if the request exceeds the timeout setting will be immediately blocked
  9. Flow Control Manager FlowRuleManager loaded rule _loadRules_
  10. The current property update rule _currentProperty ( DynamicSentinelProperty ) .updateValue (rules), bind to the value property and inform the listener list if any _

Well, the configuration is simple gray often drops, and we can see the sentinel support for the algorithm is more flexible. The core of the flow control algorithm with reference to the algorithm of google guava

Flow Control

  1. Consumer spending news
  2. Traversal message
  3. According to key into the calling context ContextUtil.enter
  4. Obtained from ThreadLocal, if it does not exist create the execution context Context
  5. Get property name cache according DefaultNode, if not, it is determined whether the maximum limit exceeding 2000, more than _NULL_CONTEXT is returned. Otherwise the lock to determine whether the air, whether there DefaultNode, does not exist, according to the name (ie key: group_name and topic_name) create _EntranceNode, and add child nodes ROOT node cache Node, a context, a context return
  6. The SphU enter key, type EntryType. OUT, in accordance with the priority into the (default is false, the priority does not open)
  7. If the process is not NULL_CONTEXT type CtEntry chain return slot
  8. If Context is null, return to the default CtEntry
  9. If the switch is not enabled global processing chain is the same as the return type CtEntry NULL_CONTEXT not processed slot chain
  10. According slot resource discovery process chain lookProcessChain, does not exist, create and cache
  11. Create a slot chain SlotChainProvider. NewSlotChain
  12. If the builder does not return empty building directly build, according to SPI or load builder, if the load is still empty, the default DefaultSlotChainBuilder
  13. The default constructor constructs slot chain link slot
public ProcessorSlotChain build() {
    ProcessorSlotChain chain = new DefaultProcessorSlotChain();
    chain.addLast(new NodeSelectorSlot());
    chain.addLast(new ClusterBuilderSlot());
    chain.addLast(new LogSlot());
    chain.addLast(new StatisticSlot());
    chain.addLast(new SystemSlot());
    chain.addLast(new AuthoritySlot());
    chain.addLast(new FlowSlot());
    chain.addLast(new DegradeSlot());

    return chain;
}
  1. According to resources, slot chain, context creation CtEntry
  2. chain into the entry slot, the default step count is 1, the priority false
  3. Return CtEntry

Slot Slot default node process each chain

DefaultProcessorSlotChain chain linked list structure AbstractLinkedProcessorSlot, namely FIFO, that is, in the presence next will continue to pass to the next node, so the actual order is executed from the last node, we follow the order to look at the specific node of each slot deal with

NodeSelectorSlot node selected slot

  1. The name of the selected nodes and placed in the context DefaultNode
  2. If the context is created for the empty cluster node is empty (that is, non-clustered mode)

ClusterBuilderSlot Clusters of the slot

  1. Create a cluster node clusterNode
  2. If the origin node is an empty string, then the node creates a corresponding StatisticNode

LogSlot log slot

  1. Direct fire next node, catch an exception and logging, blocking abnormal print log and throw Hawkeye, other anomalies directly log: "Unexpected entry exception"

StatisticSlot monitoring statistics slot

  1. Direct fire next node
  2. Statistical data records, incrementing the number of threads increaseThreadNum, in accordance with the step count increased by the number of requests addPassRequest
  3. If the origin node is not null number of threads in the same manner, the number of requests
  4. If the Entry Type IN the same manner as constants Constants. The number of threads of requests ENTRY_NODE
  5. Callback handle chain
  6. Capture priority waiting abnormal PriorityWaitException, only increase the number of threads
  7. Capture blocking abnormal BlockException, only increase the number of requests blocked
  8. Other abnormal abnormal increase in the number of requests only

SystemSlot system protection slot

  1. System Rules Manager Verification resources resourceWrapper
  2. Verification system is turned _checkSystemStatus = true (i.e., does not verify default is false) _
  3. If the resource type Entry is a direct return IN
  4. Check qps, thread, rt, the system load (load. BBR algorithm.), If cpu utilization exceeds the threshold, is the exception is thrown SystemBlockException
  5. fire the next node

AuthoritySlot black and white list Authentication slot

  1. Check black list
  2. If the certification rules there is no direct return AuthorityRule
  3. Obtain the corresponding certification rules AuthorityRule list based on resource name, if direct return empty
  4. Traverse checking rule checking, validation fails an exception is thrown AuthorityException
  5. fire the next node

FlowSlot flow control slot

  1. Check the flow
  2. Flow Control Rules Manager FlowRuleManager get traffic control rules map
  3. Gets flow control rules based on the resource name list
  4. Traversing the flow control rules, check the flow, check fails an exception is thrown FlowException
  5. fire the next node

DegradeSlot blown relegation slot

  1. Rules Manager check the fuse downgrade downgrade: DegradeRuleManager. CheckDegrade
  2. Get blown downgrade the list of rules based on the resource name
  3. If the direct return empty
  4. Traversal rule checking, verification is not through an exception is thrown DegradeException
  5. fire the next node

Flow control algorithm commonly used learning

sentinel species flow control algorithm, a total of about categories: direct denial , Warm Up , uniform line up

private static TrafficShapingController generateRater(/*@Valid*/ FlowRule rule) {
    if (rule.getGrade() == RuleConstant.FLOW_GRADE_QPS) {
        switch (rule.getControlBehavior()) {
            //令牌桶算法
            case RuleConstant.CONTROL_BEHAVIOR_WARM_UP:
                return new WarmUpController(rule.getCount(), rule.getWarmUpPeriodSec(),
                    ColdFactorProperty.coldFactor);
            //漏桶算法
            case RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER:
                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());
}

Leaky Bucket Algorithm

sentinel in RateLimiterController token bucket algorithm is used to achieve

  1. Important properties rate limit controller
  2. count: count the number of threshold
  3. maxQueueingTimeMs: The maximum number of queue timeout milliseconds
  4. If the application acquireCount <= 0 directly by
  5. If count <= 0 is rejected
  6. Calculating the average take several milliseconds per request
// Calculate the interval between every two requests.
long costTime = Math.round(1.0 * (acquireCount) / count * 1000);
  1. Calculating the average take several milliseconds per request
  2. Calculated last time by the current time by requesting desired expectedTime
// Expected pass time of this request.
long expectedTime = costTime + latestPassedTime.get();
  1. If the desired time is less than equal to the current time
  2. Last time set by
  3. Return by true
  4. If the desired time is greater than the current time (i.e. wait)
long waitTime = costTime + latestPassedTime.get() - TimeUtil.currentTimeMillis();
  1. Computing time to wait waitTime
  2. If greater than the maximum queue time waitTime reject false if
  3. Last time it takes to increase the time cost by subtracting the current time to determine again whether the queue exceeds the maximum wait time
  4. If the recovery is greater than the last time by time and returns false denial
  5. Otherwise it returns true after sleep through
// Calculate the time to wait.
long waitTime = costTime + latestPassedTime.get() - TimeUtil.currentTimeMillis();
if (waitTime > maxQueueingTimeMs) {
    return false;
} else {
    long oldTime = latestPassedTime.addAndGet(costTime);
    try {
        waitTime = oldTime - TimeUtil.currentTimeMillis();
        if (waitTime > maxQueueingTimeMs) {
            latestPassedTime.addAndGet(-costTime);
            return false;
        }
        // in race condition waitTime may <= 0
        if (waitTime > 0) {
            Thread.sleep(waitTime);
        }
        return true;
    } catch (InterruptedException e) {
    }
}

Token bucket algorithm

sentinel in WarmUpController is leaky bucket algorithm implementation, mainly to solve the kind of request pulse received by the system, even if the system over a period of stable may have a lot of processing power, it might slow down or even system downtime. Then we take a look at the implementation of the class

  1. Warm-up controller constructor important attribute
  2. count: Threshold count
  3. warmUpPeriodInSec: warm-up time in seconds
  4. coldFactor: Cooling factor
  5. warningToken: token alert = (int) (warmUpPeriodInSec * count) / (coldFactor - 1); count per second token * warm seconds, i.e. during all of the number of tokens warm / cool factor 1, guard values ​​calculated .
  6. maxToken: maximum token = warningToken + (int) (2 * warmUpPeriodInSec * count / (1.0 + coldFactor))
  7. slope:斜坡=(coldFactor - 1.0) / count / (maxToken - warningToken)
  8. FIG maximum value is about the average number of tokens per second multiplied warmUpPeriodInSec
  9. 例如:count=10,coldFactor=3,warmUpPeriodInSec=3。则warningToken=310/(3-1) = 15,maxToken=15+23*10/(1+3)=30,slope=(3-1)/10/(30-15)≈0.013
  10. Can be determined whether canPass
public boolean canPass(Node node, int acquireCount, boolean prioritized) {
    long passQps = (long) node.passQps();

    long previousQps = (long) node.previousPassQps();
    syncToken(previousQps);

    // 开始计算它的斜率
    // 如果进入了警戒线,开始调整他的qps
    long restToken = storedTokens.get();
    if (restToken >= warningToken) {
        long aboveToken = restToken - warningToken;
        // 消耗的速度要比warning快,但是要比慢
        // current interval = restToken*slope+1/count
        double warningQps = Math.nextUp(1.0 / (aboveToken * slope + 1.0 / count));
        if (passQps + acquireCount <= warningQps) {
            return true;
        }
    } else {
        if (passQps + acquireCount <= count) {
            return true;
        }
    }

    return false;
}
  1. Synchronous tokens syncToken
protected void syncToken(long passQps) {
    long currentTime = TimeUtil.currentTimeMillis();
    currentTime = currentTime - currentTime % 1000;
    long oldLastFillTime = lastFilledTime.get();
    if (currentTime <= oldLastFillTime) {
        return;
    }

    long oldValue = storedTokens.get();
    long newValue = coolDownTokens(currentTime, passQps);

    if (storedTokens.compareAndSet(oldValue, newValue)) {
        long currentValue = storedTokens.addAndGet(0 - passQps);
        if (currentValue < 0) {
            storedTokens.set(0L);
        }
        lastFilledTime.set(currentTime);
    }
}
  1. Current time erase one hundred, ten, digits and other bits rounding
  2. Get the last time filled token, if the current time is less than the treated equal to the last fill time is directly returned (because all bits erase several seconds after the rounding, i.e. once per filling)
  3. Gets the last population value storedTokens.get ()
  4. Cooling token
private long coolDownTokens(long currentTime, long passQps) {
    long oldValue = storedTokens.get();
    long newValue = oldValue;

    // 添加令牌的判断前提条件:
    // 当令牌的消耗程度远远低于警戒线的时候
    if (oldValue < warningToken) {
        newValue = (long)(oldValue + (currentTime - lastFilledTime.get()) * count / 1000);
    } else if (oldValue > warningToken) {
        if (passQps < (int)count / coldFactor) {
            newValue = (long)(oldValue + (currentTime - lastFilledTime.get()) * count / 1000);
        }
    }
    return Math.min(newValue, maxToken);
}
  1. If the token is smaller than the old alert token, a new token = (current time - last fill time / 1000 (i.e., into second)) * count (threshold count) + old token
  2. If the token is not less than the old token alert, qps the time window is less than (count / cooling factor). = New token calculated by the same token is smaller than the warning algorithms. If it is not greater than or equal to add new token
  3. Returns the minimum value between the two maximum token and a new token
  4. If successful it will set up a new token is the last time through the window of qps minus, if after subtracting less than 0 is set to 0
  5. Set filling time
  6. Complete sync token
  7. Get a token from the token bucket storeTokens
  8. If the current token is greater than or equal vigilance token
  9. Minus the current token alert token (tokens beyond the warning section) aboveToken
  10. Calculated from the slope alert qps
  11. The current application system qps + acquireCount <= QPS alert; back through true, otherwise returns false rejection
  12. If the current token is smaller than the token alert
  13. Current application value qps + acquireCount <= count (threshold count) back through true, otherwise returns false rejection

Guess you like

Origin blog.csdn.net/u010597819/article/details/88927028