The basic working principle and current limiting principle of Sentinel were introduced in the previous article. This paper will analyze the principle of fuse – break degradation from the perspective of source code. Meltdown operations are provided at the end of the Slot processing chain and are handled by a class called DegradeSlot
@SpiOrder(-1000) public class DegradeSlot extends AbstractLinkedProcessorSlot<DefaultNode> { @Override public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... Args) throws Throwable {/ / fusing relegation judgment DegradeRuleManager checkDegrade (resourceWrapper, the context node, count); fireEntry(context, resourceWrapper, node, count, prioritized, args); } @Override public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) { fireExit(context, resourceWrapper, count, args); }}Copy the code
Degrade degrade Manager checkDegrade is a general manager method
public static void checkDegrade(ResourceWrapper resource, Context context, DefaultNode node, Int count) throws BlockException {// Obtain resource melting rules Set< assist ule> rules = assist ules. Get (resource-.getName ()); if (rules == null) { return; } // Reviews each fuse rule to check whether it meets the melting conditions. For (DegradeRule rule: Rules) { rule.passCheck(context, node, count)) { throw new DegradeException(rule.getLimitApp(), rule); }}}Copy the code
The circuit breaker is judged one by one according to the rules set for resources. If one condition is not met, a DegradeException exception is thrown. So how exactly is the circuit breaker judgment done? The passCheck method is separated into three groups to achieve survival. It provides a general overview of the passCheck method.
Private double count; Private int timeWindow; // Fuse policy (0: slow call, 1: abnormal rate, 2: abnormal number) private int grade = ruleconstant. DEGRADE_GRADE_RT; // Fuse policy (0: slow call, 1: abnormal rate, 2: abnormal number) private int grade = RuleConstant. /** * For slow calls, if the number of slow calls is less than its value (default is 5), * * @since 1.7.0 */ private int rtSlowRequestAmount = ruleconstant. DEGRADE_DEFAULT_SLOW_REQUEST_AMOUNT; /** * For outliers, if the number of outliers is less than its value (default is 5), * * @since 1.7.0 */ private int minRequestAmount = ruleconstant. DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;Copy the code
The realization principle of circuit breaker is simply that in a set window time, according to the set specific circuit breaker strategy, judge whether the corresponding count statistics exceeds the threshold value, if so, the circuit breaker mechanism will be triggered. Deep passCheck source code
Private AtomicLong passCount = new AtomicLong(0); Private final AtomicBoolean cut = new AtomicBoolean(false); public boolean passCheck(Context context, DefaultNode node, int acquireCount, Object... If (cut. Get ()) {return false; } / / access to resources statistical node count ClusterNode ClusterNode = ClusterBuilderSlot. GetClusterNode (enclosing getResource ()); if (clusterNode == null) { return true; } // If (grade == ruleconstant.degrade_grade_rt) {double rt = clusterNode.avgrt (); If (rt < this.count) {passcount.set (0); if (rt < this.count) {passcount.set (0); return true; } / / if slow call number is less than the default minimum threshold number (5), is not for fusing downgrade the if (passCount. IncrementAndGet () < rtSlowRequestAmount) {return true; } else if (grade == ruleconstant. DEGRADE_GRADE_EXCEPTION_RATIO) {// Number of exceptions per second double exception = clusterNode.exceptionQps(); Double Success = ClusterNode.successQps (); Double total = clusterNode.totalqps (); If (total < minRequestAmount) {return true; if (total < minRequestAmount) {return true; } double realSuccess = success-exception double realSuccess = success-exception double realSuccess = success-exception; if (realSuccess <= 0 && exception < minRequestAmount) { return true; If (exception/success < count) {return true; if (exception/success < count) {return true; } else if (grade == ruleconstant. DEGRADE_GRADE_EXCEPTION_COUNT) {// Notice, This exception is per minute statistics of double exception. = clusterNode totalException (); If (exception < count) {return true; }} // Reset the time window for slow call statistics, where CAS is used to set flag bit to prevent concurrency. The reset of the timeWindow depends on the scheduled task. When the timeWindow time expires, If (cut.compareAndSet(false, true)) {ResetTask ResetTask = new ResetTask(this); pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS); } return false; } private static final class ResetTask implements Runnable {private final class DegradeRule rule; ResetTask(DegradeRule rule) { this.rule = rule; } @override public void run() {rule-passcount.set (0); // Fuse flag bit rul.cut. Set (false); }}Copy the code
The above code describes the core process of fuse downgrading. For the above code, attention should be paid to:
- Slow calls are implemented by counting the number of slow calls in a time window
- The outlier rate is the ratio of the number of outliers per second to the number of successes to judge whether triggering conditions are met
- Outliers are calculated for outliers per minute
When a fuse is triggered, the flag bit is set to true and lasts the timeWindow length that the developer set when setting the fuse downgrade rule. The above is the realization process of the whole fuse downgrade. From the point of view of the code, the fuse window is updated through a scheduled task, and the design is relatively novel.