系列
- Sentinel流程介紹
- Sentinel資源節(jié)點樹構(gòu)成
- Sentinel滑動窗口介紹
- Sentinel流量控制
- Sentinel的職責(zé)鏈slot介紹
- Sentinel熔斷降級
- Sentinel Dashboard和應(yīng)用通信
- Sentinel 控制臺
相同資源名場景分析
Entry entry = null;
try {
entry = SphU.entry("abc");
entry = SphU.entry("abc");
} catch (BlockException e1) {
} finally {
if (entry != null) {
entry.exit();
}
}
創(chuàng)建Context
public class ContextUtil {
protected static Context trueEnter(String name, String origin) {
Context context = contextHolder.get();
if (context == null) {
Map<String, DefaultNode> localCacheNameMap = contextNameNodeMap;
DefaultNode node = localCacheNameMap.get(name);
if (node == null) {
if (localCacheNameMap.size() > Constants.MAX_CONTEXT_NAME_SIZE) {
setNullContext();
return NULL_CONTEXT;
} else {
LOCK.lock();
try {
node = contextNameNodeMap.get(name);
if (node == null) {
if (contextNameNodeMap.size() > Constants.MAX_CONTEXT_NAME_SIZE) {
setNullContext();
return NULL_CONTEXT;
} else {
node = new EntranceNode(new StringResourceWrapper(name, EntryType.IN), null);
// Add entrance node.
Constants.ROOT.addChild(node);
Map<String, DefaultNode> newMap = new HashMap<>(contextNameNodeMap.size() + 1);
newMap.putAll(contextNameNodeMap);
newMap.put(name, node);
contextNameNodeMap = newMap;
}
}
} finally {
LOCK.unlock();
}
}
}
// 這里的node設(shè)置的是Context的EntranceNode
context = new Context(node, name);
context.setOrigin(origin);
contextHolder.set(context);
}
return context;
}
}
- 首先在ThreadLocal獲取,獲取不到就創(chuàng)建,不然就返回
- 然后再Map中根據(jù)ContextName找一個Node
- 沒有找到Node就加鎖的方式,創(chuàng)建一個EntranceNode,然后放入Map中
- 創(chuàng)建Context,設(shè)置node,name,origin,再放入ThreadLocal中

第一次創(chuàng)建Entry
Entry e = new CtEntry(resourceWrapper, chain, context);
class CtEntry extends Entry {
protected Entry parent = null;
protected Entry child = null;
protected ProcessorSlot<Object> chain;
protected Context context;
protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;
CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
super(resourceWrapper);
this.chain = chain;
this.context = context;
setUpEntryFor(context);
}
private void setUpEntryFor(Context context) {
// The entry should not be associated to NullContext.
if (context instanceof NullContext) {
return;
}
// 首次返回為null
this.parent = context.getCurEntry();
if (parent != null) {
((CtEntry) parent).child = this;
}
// 設(shè)置Context的curEntry為當(dāng)前的CtEntry
context.setCurEntry(this);
}
}

第一次執(zhí)行NodeSelectorSlot
@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
throws Throwable {
DefaultNode node = map.get(context.getName());
if (node == null) {
synchronized (this) {
node = map.get(context.getName());
if (node == null) {
node = new DefaultNode(resourceWrapper, null);
HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
cacheMap.putAll(map);
cacheMap.put(context.getName(), node);
map = cacheMap;
// 構(gòu)建調(diào)用樹,添加entranceNode的子節(jié)點
((DefaultNode) context.getLastNode()).addChild(node);
}
}
}
// 設(shè)置Context的當(dāng)前節(jié)點
context.setCurNode(node);
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
}
public class Context {
private final String name;
private DefaultNode entranceNode;
private Entry curEntry;
private String origin = "";
private final boolean async;
public Node getLastNode() {
if (curEntry != null && curEntry.getLastNode() != null) {
return curEntry.getLastNode();
} else {
return entranceNode;
}
}
public Context setCurNode(Node node) {
this.curEntry.setCurNode(node);
return this;
}
}

第二次創(chuàng)建Entry
Entry e = new CtEntry(resourceWrapper, chain, context);
class CtEntry extends Entry {
protected Entry parent = null;
protected Entry child = null;
protected ProcessorSlot<Object> chain;
protected Context context;
protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;
CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
super(resourceWrapper);
this.chain = chain;
this.context = context;
setUpEntryFor(context);
}
private void setUpEntryFor(Context context) {
// The entry should not be associated to NullContext.
if (context instanceof NullContext) {
return;
}
// 首次返回為null
this.parent = context.getCurEntry();
if (parent != null) {
((CtEntry) parent).child = this;
}
// 設(shè)置Context的curEntry為當(dāng)前的CtEntry
context.setCurEntry(this);
}
}

第二次執(zhí)行NodeSelectorSlot
@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
throws Throwable {
DefaultNode node = map.get(context.getName());
if (node == null) {
synchronized (this) {
node = map.get(context.getName());
if (node == null) {
node = new DefaultNode(resourceWrapper, null);
HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
cacheMap.putAll(map);
cacheMap.put(context.getName(), node);
map = cacheMap;
// 構(gòu)建調(diào)用樹,添加entranceNode的子節(jié)點
((DefaultNode) context.getLastNode()).addChild(node);
}
}
}
// 設(shè)置Context的當(dāng)前節(jié)點
context.setCurNode(node);
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
}
public class Context {
private final String name;
private DefaultNode entranceNode;
private Entry curEntry;
private String origin = "";
private final boolean async;
public Node getLastNode() {
if (curEntry != null && curEntry.getLastNode() != null) {
return curEntry.getLastNode();
} else {
return entranceNode;
}
}
public Context setCurNode(Node node) {
this.curEntry.setCurNode(node);
return this;
}
}

不同資源名場景分析
Entry entry = null;
try {
entry = SphU.entry("abc");
entry = SphU.entry("abcd");
} catch (BlockException e1) {
} finally {
if (entry != null) {
entry.exit();
}
}
第一次創(chuàng)建Entry
Entry e = new CtEntry(resourceWrapper, chain, context);
class CtEntry extends Entry {
protected Entry parent = null;
protected Entry child = null;
protected ProcessorSlot<Object> chain;
protected Context context;
protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;
CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
super(resourceWrapper);
this.chain = chain;
this.context = context;
setUpEntryFor(context);
}
private void setUpEntryFor(Context context) {
// The entry should not be associated to NullContext.
if (context instanceof NullContext) {
return;
}
// 首次返回為null
this.parent = context.getCurEntry();
if (parent != null) {
((CtEntry) parent).child = this;
}
// 設(shè)置Context的curEntry為當(dāng)前的CtEntry
context.setCurEntry(this);
}
}

第一次執(zhí)行NodeSelectorSlot
@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
throws Throwable {
DefaultNode node = map.get(context.getName());
if (node == null) {
synchronized (this) {
node = map.get(context.getName());
if (node == null) {
node = new DefaultNode(resourceWrapper, null);
HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
cacheMap.putAll(map);
cacheMap.put(context.getName(), node);
map = cacheMap;
// 構(gòu)建調(diào)用樹,添加entranceNode的子節(jié)點
((DefaultNode) context.getLastNode()).addChild(node);
}
}
}
// 設(shè)置Context的當(dāng)前節(jié)點
context.setCurNode(node);
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
}
public class Context {
private final String name;
private DefaultNode entranceNode;
private Entry curEntry;
private String origin = "";
private final boolean async;
public Node getLastNode() {
if (curEntry != null && curEntry.getLastNode() != null) {
return curEntry.getLastNode();
} else {
return entranceNode;
}
}
public Context setCurNode(Node node) {
this.curEntry.setCurNode(node);
return this;
}
}

第二次創(chuàng)建Entry
Entry e = new CtEntry(resourceWrapper, chain, context);
class CtEntry extends Entry {
protected Entry parent = null;
protected Entry child = null;
protected ProcessorSlot<Object> chain;
protected Context context;
protected LinkedList<BiConsumer<Context, Entry>> exitHandlers;
CtEntry(ResourceWrapper resourceWrapper, ProcessorSlot<Object> chain, Context context) {
super(resourceWrapper);
this.chain = chain;
this.context = context;
setUpEntryFor(context);
}
private void setUpEntryFor(Context context) {
// The entry should not be associated to NullContext.
if (context instanceof NullContext) {
return;
}
// 首次返回為null
this.parent = context.getCurEntry();
if (parent != null) {
((CtEntry) parent).child = this;
}
// 設(shè)置Context的curEntry為當(dāng)前的CtEntry
context.setCurEntry(this);
}
}

第二次執(zhí)行NodeSelectorSlot
@Spi(isSingleton = false, order = Constants.ORDER_NODE_SELECTOR_SLOT)
public class NodeSelectorSlot extends AbstractLinkedProcessorSlot<Object> {
private volatile Map<String, DefaultNode> map = new HashMap<String, DefaultNode>(10);
@Override
public void entry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
throws Throwable {
DefaultNode node = map.get(context.getName());
if (node == null) {
synchronized (this) {
node = map.get(context.getName());
if (node == null) {
node = new DefaultNode(resourceWrapper, null);
HashMap<String, DefaultNode> cacheMap = new HashMap<String, DefaultNode>(map.size());
cacheMap.putAll(map);
cacheMap.put(context.getName(), node);
map = cacheMap;
// 構(gòu)建調(diào)用樹,第一次添加entranceNode的子節(jié)點
// 第二次添加到當(dāng)前節(jié)點的父節(jié)點當(dāng)中
((DefaultNode) context.getLastNode()).addChild(node);
}
}
}
// 設(shè)置Context的當(dāng)前節(jié)點
context.setCurNode(node);
fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
}
public class Context {
private final String name;
private DefaultNode entranceNode;
private Entry curEntry;
private String origin = "";
private final boolean async;
public Node getLastNode() {
if (curEntry != null && curEntry.getLastNode() != null) {
return curEntry.getLastNode();
} else {
return entranceNode;
}
}
public Context setCurNode(Node node) {
this.curEntry.setCurNode(node);
return this;
}
}
class CtEntry extends Entry {
protected Entry parent = null;
protected Entry child = null;
@Override
public Node getLastNode() {
return parent == null ? null : parent.getCurNode();
}
}
-
因為資源名不同所以對應(yīng)的職責(zé)鏈條,因此NodeSelectorSlot會重新創(chuàng)建DefaultNode。
