2.3.2 Entry
在调用链上,一个资源对应一个Entry实例。可以从Context中获取调用链上当前访问到的资源的DefaultNode实例,而DefaultNode实例实际是从Context实例的curEntry字段中获取的。Context实例的curEntry字段引用当前资源的DefaultNode实例,以及资源相对当前调用来源的StatisticNode实例。
Entry抽象类定义了如下字段。
• curNode:当前资源的DefaultNode实例。
• originNode:资源相对当前调用来源的StatisticNode实例。
• resourceWrapper:资源ID。
CtEntry是Entry的直接子类,CtEntry用于维护父子Entry关系,每一次调用SphU类的entry方法都会创建一个CtEntry实例。
CtEntry类中声明的字段信息如下述代码所示。
• parent:当前Entry实例指向的父Entry。
• child:当前Entry实例指向的下一个Entry实例。
• chain:当前资源的ProcessorSlotChain实例,Sentinel会为每个资源创建且仅创建一个ProcessorSlotChain实例。
• context:调用链上的Context实例。
如果调用链上多次调用SphU类的entry方法(调用链上有多个资源),那么调用链上这些资源的CtEntry实例会构成一个双向链表。每次创建CtEntry实例都会将Context实例的curEntry字段设置为这个新的CtEntry实例。双向链表的作用就是在调用CtEntry类的exit方法时,能够将Context实例的curEntry字段还原为引用调用链上前一个CtEntry实例。
类似于Java虚拟机上栈桢的入栈和出栈。
以2.3.1节的天气预报例子进行说明,在服务B收到服务A的请求时,Sentinel在拦截器中会调用SphU类的entry方法创建一个CtEntry实例,取名为ctEntry1,此时的ctEntry1的父节点为空。当服务B向服务C发起调用时,Sentinel会拦截请求的发起,调用SphU类的entry方法创建一个CtEntry实例,取名为ctEntry2,此时ctEntry2的父节点指向ctEntry1,ctEntry1的子节点指向ctEntry2,如图2.7所示。
图2.7 CtEntry双向链表