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

This paper is the first analysis of the Sentinel principle. Due to the short time exposure to this middleware, there may be some understanding bias. I hope we can actively communicate and correct. The main content of the article is mainly read some of the gods of the article, and add their own understanding to write.

The main reference articles are found on Sentinel’s Github at the following address: Reference articles

The main functions of Sentinel are flow control and fuse downgrading. The specific concepts were introduced in the current limiting and fusing section of Dubbo, and will not be described here.

Here’s a quick example of how to use it.

public static void main(String[] args) {

    try {

        Context context=ContextUtil.enter("context1");

        Entry entry=SphU.entry("HelloWorld");

        entry.exit();

        ContextUtil.exit();

    } catch (BlockException ex) {

        // Handle flow-controlled logic

        System.out.println("blocked!");

    }catch (Exception e){

        e.printStackTrace();

    }

}

Copy the code
try (Entry entry = SphU.entry("HelloWorld")) {

    // Your business logic here.

    System.out.println("hello world");

catch (BlockException e) {

    // Handle rejected request.

    e.printStackTrace();

}

Copy the code

The above are two typical flow control examples. One obvious difference the reader will notice is that the Context class, which is used to represent the Context of a call, does not really matter, as discussed below.

There is also an important class Entry in the example. The parameter HelloWorld can be seen as a resource name, but we need to define some rules before using it. You can define a rule about flow control using the following method:

private void initFlowQpsRule(a) {

    List<FlowRule> rules = new ArrayList<>();

    FlowRule rule = new FlowRule(resourceName);

    // set limit qps to 20

    rule.setCount(20);

    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);

    rule.setLimitApp("default");

    rules.add(rule);

    FlowRuleManager.loadRules(rules);

}

Copy the code

If no exception is reported when sphu.entry (“HelloWorld”) is called, the business code can be executed. If an error message is displayed, the current conditions are not met and the following service codes are rejected.

Several core concepts

Resource

A resource is a core concept in Sentinel. It can be a service provided by an application, another service invoked by an application, or a piece of code. When a service has a large number of requests and is often overwhelmed by a sudden increase in traffic, resulting in performance degradation or unavailability, we can define a Sentinel resource to adjust the requests through this resource for traffic control and service degradation.

The class that represents a specific resource in Sentinel is a ResourceWrapper.

public abstract class ResourceWrapper {

# resource name

    protected final String name;

# Inbound or outbound

    protected final EntryType entryType;

# Resource type

    protected final int resourceType;

Copy the code

Entry

Entry is a token used in Sentinel to indicate whether or not the stream has passed the limit. If it returns normally, then you can access the sentinel protected backend service. Otherwise, Sentinel will throw a BlockException. In addition, it holds some basic information about the entry() method being executed this time. An Entry is created for each resource invocation.

public abstract class Entry implements AutoCloseable {

# The creation time of the current Entry is mainly used to calculate RT later

    private long createTime;

# The node associated with the current Entry. This node records statistics about the resource in the current context

    private Node curNode;

The source of the call to the current Entry, usually the application name of the caller

    private Node originNode;

    private Throwable error;

The resource associated with the current Entry

    protected ResourceWrapper resourceWrapper;

Copy the code
class CtEntry extends Entry {

    protected Entry parent = null;

    protected Entry child = null;

    protected ProcessorSlot<Object> chain;

    protected Context context;

Copy the code

Maybe it’s a little abstract, but let me draw on someone else’s example, which is very graphic.

From the figure we can see that there is a user-center –> getUserInfo –> getOrderInfo call link. From the code, we know that user-Center is a context name and getUserInfo and getOrderInfo are two resource names.

In the example above, another Entry is called within an Entry, and there is a link. When the sphu.entry () method is called multiple times within a context, a call tree is created, and the nodes of the tree are maintained by parent and child relationships.

Node

Node stores real-time resource statistics, such as passQps, blockQps, and RT.

StatisticNode
StatisticNode
DefaultNode
ClusterNode
DefaultNode
EntranceNode

EntranceNode is an EntranceNode for each context. This node is directly attached to root and is globally unique. Each context has an EntranceNode. DefaultNode records current real-time data. Each DefaultNode is associated with a resource and a ClusterNode. Defaultnodes with the same resources are associated with the same clusterNode.

public interface Node extends OccupySupport.DebugSupport {

    long totalRequest(a);

    long totalPass(a);

    long totalSuccess(a);

Copy the code
public class DefaultNode extends StatisticNode {

    private ResourceWrapper id;

    private volatile Set<Node> childList = new HashSet<>();

    private ClusterNode clusterNode;

Copy the code

Context

public class Context {

    // Context name

    private final String name;

    // The entry node of the current call chain

    private DefaultNode entranceNode;

   // Call the entry currently being processed in the chain

    private Entry curEntry;

    // The source of this context (usually representing a different caller, such as a service consumer name or source IP)

    private String origin = "";

Copy the code

Context represents the call link Context, through all entries in a call link. Each call to sphu.entry () needs to be executed in a context. If there is no context when there is no current execution, the framework uses the default context, sentinel_default_context.

The Context is stored in a ThreadLocal and is first fetched from ThreadLocal each time it is executed. If the Context is null, then another Context will be created.

When exit is executed on Entry, if the parent of the current Entry is null, it indicates that the current Entry is the topmost node and the Entry of this context has been executed. Therefore, you need to set the context to NULL to clear it from ThreadLocal.

So that’s an important introduction to entity classes.

Sentinel core class analysis Sentinel principle – Entity class Ali Sentinel source code analysis

This article is formatted using MDNICE