Wechat public account: the landlord’s small black road is far away, the future is better learning is boundless, we come on together!

In this article, the principle of fuse downgrading will be explained.

The fuse degrade policy is implemented in Anyhow and calls the Entry () method.

public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args)

        throws Throwable 
{

        DegradeRuleManager.checkDegrade(resourceWrapper, context, node, count);

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

    }

Copy the code

The following logic gets all the fuse breakers from the Map cache in Survival Manager based on the current resource name. Then walk through the rules and judge in turn. If a circuit breaker is required, a DegradeException exception is thrown.

private static final Map<String, Set<DegradeRule>> degradeRules = new ConcurrentHashMap<>();

public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, int count)

        throws BlockException 
{



        Set<DegradeRule> rules = degradeRules.get(resource.getName());

        if (rules == null) {

            return;

        }



        for (DegradeRule rule : rules) {

            if(! rule.passCheck(context, node, count)) {

                throw new DegradeException(rule.getLimitApp(), rule);

            }

        }

    }

Copy the code

To determine this, call the passCheck() method in the Survival ule.

It all adds up to a General survival ule.

public class DegradeRule extends AbstractRule {



    // The size is the maximum number of available virtual machines

    private static ScheduledExecutorService pool = Executors.newScheduledThreadPool(

        Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("sentinel-degrade-reset-task".true));

    // RT threshold or abnormal ratio threshold counts

    private double count;

    // Downgrade recovery timeout (in seconds) when a downgrade occurs

    private int timeWindow;

    // Demote policy (0: average RT, 1: exception ratio, 2: exception count).

    private int grade = RuleConstant.DEGRADE_GRADE_RT;

    // The minimum number of consecutive slow response requests that trigger RT response fuses

    // The default value is 5

    private int rtSlowRequestAmount = RuleConstant.DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT;

   // The minimum number of requests to trigger a fuse

    private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;

    

    private AtomicLong passCount = new AtomicLong(0);

    // Whether a downgrade has occurred

    private final AtomicBoolean cut = new AtomicBoolean(false);

Copy the code

It all adds up to a DegradeRule.

public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... args) {

        // If you are currently in the degraded phase, return false

        if (cut.get()) {

            return false;

        }

        // Obtain the ClusterNode for the resource

        ClusterNode clusterNode = ClusterBuilderSlot.getClusterNode(this.getResource());

        if (clusterNode == null) {

            return true;

        }

        // If the request is judged according to the request response time RT

        if (grade == RuleConstant.DEGRADE_GRADE_RT) {

            // Get the average response time for this node

            double rt = clusterNode.avgRt();

            // If the current average response time is less than the threshold, pass and reset passcount to 0

            if (rt < this.count) {

                passCount.set(0);

                return true;

            }

            // The current average response time is greater than the threshold

            // If the number of consecutive requests is less than rtSlowRequestAmount, the status is allowed

            if (passCount.incrementAndGet() < rtSlowRequestAmount) {

                return true;

            }

        // If the exception ratio is used to judge

        } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {

            // Current number of exceptions

            double exception = clusterNode.exceptionQps();

            // Number of successful requests

            double success = clusterNode.successQps();

            // Total requests

            double total = clusterNode.totalQps();

            // If total amount is less than minRequestAmount, the request will pass.

            if (total < minRequestAmount) {

                return true;

            }



            // In the same align statistics time window,

            // "success" (aka. completed count) = exception count + non-exception count (realSuccess)

            double realSuccess = success - exception;

            // If the true number of successes is less than 0 and the number of exceptions is less than minRequestAmount

            if (realSuccess <= 0 && exception < minRequestAmount) {

                return true;

            }

            // If the proportion of exceptions is smaller than the threshold

            if (exception / success < count) {

                return true;

            }

        // If the number of exceptions is specified

        } else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {

            double exception = clusterNode.totalException();

            if (exception < count) {

                return true;

            }

        }

        // Atoms are updated to true when fuse downgrade is triggered

        // Start a timed task, set the fusing state to false after the fusing time expires, and reset the pass count to 0

        if (cut.compareAndSet(false.true)) {

            ResetTask resetTask = new ResetTask(this);

            pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS);

        }

        return false;

    }

Copy the code
private static final class ResetTask implements Runnable {

        private DegradeRule rule;

        ResetTask(DegradeRule rule) {

            this.rule = rule;

        }



        @Override

        public void run(a) {

            rule.passCount.set(0);

            rule.cut.set(false);

        }

    }

Copy the code

Compared to flow control, fuse downgrading is simple.

Reference article:

Sentinel Survival eslot fuse degrades