Sentinel 的基本使用
ContextUtil.enter("上下文名称,例如:sentinel_spring_web_context");
Entry entry = null;
try {
entry = SphU.entry("资源名称,例如:/rpc/openfein/demo", EntryType.IN (或者 EntryType.OUT));
// 执行业务方法
return doBusiness();
} catch (Exception e) {
if (!(e instanceof BlockException)) {
Tracer.trace(e);
}
throw e;
} finally {
if (entry != null) {
entry.exit(1);
}
ContextUtil.exit();
}
注意,doBusiness()业务方法内部也可能存在另一个资源的entry和exit操作。
ROOT 与调用树
Constants 常量类用于声明全局静态常量,Constants 有一个 ROOT 静态字段,类型为 EntranceNode。
在调用 ContextUtil#enter 方法时,如果还没有为当前入口创建 EntranceNode,则会为当前入口创建 EntranceNode,将其赋值给 Context.entranceNode,同时也会将这个 EntranceNode 添加到 Constants.ROOT 的子节点(childList)。资源对应的 DefaultNode 则是在 NodeSelectorSlot 中创建,并赋值给 Context.curEntry.curNode。
Constants.ROOT、Context.entranceNode 与 Entry.curNode 三者关系如下图所示。
创建上下文 ContextUtil
public class ContextUtil {
//contextHolder存放本次链路context
private static ThreadLocal<Context> contextHolder = new ThreadLocal<>();
//全局map,存放了所有的EntranceNode key: contextName value:EntranceNode
private static volatile Map<String, DefaultNode> contextNameNodeMap = new HashMap<>();
//初始化默认的上下文(更确切的说是初始化缺省上下文对应的EntranceNode,并加入contextNameNodeMap和Constants.ROOT的子节点中。上下文对象每条链路对应一个,所以不可在static中初始化)
static {
// Cache the entrance node for default context.
initDefaultContext();
}
private static void initDefaultContext() {
String defaultContextName = Constants.CONTEXT_DEFAULT_NAME;
EntranceNode node = new EntranceNode(new StringResourceWrapper(defaultContextName, EntryType.IN), null);
Constants.ROOT.addChild(node);
contextNameNodeMap.put(defaultContextName, node);
}
//创建上下文的方法
protected static Context trueEnter(String name, String origin) {
Context context = contextHolder.get();
if (context == null) {
Map<String, DefaultNode> localCacheNameMap = contextNa