mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2026-05-11 04:04:35 +08:00
u
This commit is contained in:
@@ -25,13 +25,7 @@
|
||||
<meta name="generator" content="Hexo 4.2.0">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="book-container">
|
||||
|
||||
<div class="book-sidebar">
|
||||
@@ -55,289 +49,148 @@
|
||||
<li><a href="/" class="current-tab">首页</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li><a href="../">上一级</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/01 开篇词:一次服务雪崩问题排查经历.md.html">01 开篇词:一次服务雪崩问题排查经历.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/02 为什么需要服务降级以及常见的几种降级方式.md.html">02 为什么需要服务降级以及常见的几种降级方式.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/03 为什么选择 Sentinel,Sentinel 与 Hystrix 的对比.md.html">03 为什么选择 Sentinel,Sentinel 与 Hystrix 的对比.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/04 Sentinel 基于滑动窗口的实时指标数据统计.md.html">04 Sentinel 基于滑动窗口的实时指标数据统计.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/05 Sentinel 的一些概念与核心类介绍.md.html">05 Sentinel 的一些概念与核心类介绍.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
<a class="current-tab" href="/专栏/深入理解 Sentinel(完)/06 Sentinel 中的责任链模式与 Sentinel 的整体工作流程.md.html">06 Sentinel 中的责任链模式与 Sentinel 的整体工作流程.md.html</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/07 Java SPI 及 SPI 在 Sentinel 中的应用.md.html">07 Java SPI 及 SPI 在 Sentinel 中的应用.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/08 资源指标数据统计的实现全解析(上).md.html">08 资源指标数据统计的实现全解析(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/09 资源指标数据统计的实现全解析(下).md.html">09 资源指标数据统计的实现全解析(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/10 限流降级与流量效果控制器(上).md.html">10 限流降级与流量效果控制器(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/11 限流降级与流量效果控制器(中).md.html">11 限流降级与流量效果控制器(中).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/12 限流降级与流量效果控制器(下).md.html">12 限流降级与流量效果控制器(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/13 熔断降级与系统自适应限流.md.html">13 熔断降级与系统自适应限流.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/14 黑白名单限流与热点参数限流.md.html">14 黑白名单限流与热点参数限流.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/15 自定义 ProcessorSlot 实现开关降级.md.html">15 自定义 ProcessorSlot 实现开关降级.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/16 Sentinel 动态数据源:规则动态配置.md.html">16 Sentinel 动态数据源:规则动态配置.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/17 Sentinel 主流框架适配.md.html">17 Sentinel 主流框架适配.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/18 Sentinel 集群限流的实现(上).md.html">18 Sentinel 集群限流的实现(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/19 Sentinel 集群限流的实现(下).md.html">19 Sentinel 集群限流的实现(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/20 结束语:Sentinel 对应用的性能影响如何?.md.html">20 结束语:Sentinel 对应用的性能影响如何?.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/21 番外篇:Sentinel 1.8.0 熔断降级新特性解读.md.html">21 番外篇:Sentinel 1.8.0 熔断降级新特性解读.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||||
|
||||
<div class="sidebar-toggle-inner"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function add_inner() {
|
||||
@@ -347,9 +200,6 @@
|
||||
inner.classList.add('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function remove_inner() {
|
||||
|
||||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||||
@@ -357,9 +207,6 @@
|
||||
inner.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sidebar_toggle() {
|
||||
|
||||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||||
@@ -389,9 +236,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function open_sidebar() {
|
||||
|
||||
let sidebar = document.querySelector('.book-sidebar')
|
||||
@@ -415,13 +259,7 @@ function hide_canvas() {
|
||||
overlay.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div class="off-canvas-content">
|
||||
|
||||
<div class="columns">
|
||||
@@ -505,9 +343,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>如何去掉 ProcessorSlot 或者添加自定义的 ProcessorSlot,下一篇再作介绍。</p>
|
||||
@@ -533,9 +368,6 @@ function hide_canvas() {
|
||||
void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>例如实现熔断降级功能的 DegradeSlot,其在 entry 方法中检查资源当前统计的指标数据是否达到配置的熔断降级规则的阈值,如果是则触发熔断,抛出一个 DegradeException(必须是 BlockException 的子类),而 exit 方法什么也不做。</p>
|
||||
@@ -567,9 +399,6 @@ function hide_canvas() {
|
||||
// 当前节点的下一个节点
|
||||
|
||||
private AbstractLinkedProcessorSlot<?> next = null;
|
||||
|
||||
|
||||
|
||||
public void setNext(AbstractLinkedProcessorSlot<?> next) {
|
||||
|
||||
this.next = next;
|
||||
@@ -577,9 +406,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>实现责任链调用是由前一个 AbstractLinkedProcessorSlot 调用 fireEntry 方法或者 fireExit 方法,在 fireEntry 与 fireExit 方法中调用下一个 AbstractLinkedProcessorSlot(next)的 entry 方法或 exit 方法。AbstractLinkedProcessorSlot 的 fireEntry 与 fireExit 方法的实现源码如下:</p>
|
||||
@@ -589,17 +415,11 @@ function hide_canvas() {
|
||||
// 当前节点的下一个节点
|
||||
|
||||
private AbstractLinkedProcessorSlot<?> next = null;
|
||||
|
||||
|
||||
|
||||
public void setNext(AbstractLinkedProcessorSlot<?> next) {
|
||||
|
||||
this.next = next;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void fireEntry(Context context, ResourceWrapper resourceWrapper, Object obj, int count, boolean prioritized, Object... args)
|
||||
@@ -617,9 +437,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void fireExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||
@@ -635,9 +452,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>ProcessorSlotChain 也继承 AbstractLinkedProcessorSlot,只不过加了两个方法:提供将一个 ProcessorSlot 添加到链表的头节点的 addFirst 方法,以及提供将一个 ProcessorSlot 添加到链表末尾的 addLast 方法。</p>
|
||||
@@ -649,9 +463,6 @@ function hide_canvas() {
|
||||
// first,指向链表头节点
|
||||
|
||||
AbstractLinkedProcessorSlot<?> first = new AbstractLinkedProcessorSlot<Object>() {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void entry(Context context, ResourceWrapper resourceWrapper, Object t, int count, boolean prioritized, Object... args)
|
||||
@@ -661,9 +472,6 @@ function hide_canvas() {
|
||||
super.fireEntry(context, resourceWrapper, t, count, prioritized, args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||
@@ -671,17 +479,11 @@ function hide_canvas() {
|
||||
super.fireExit(context, resourceWrapper, count, args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// end,指向链表尾节点
|
||||
|
||||
AbstractLinkedProcessorSlot<?> end = first;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void addFirst(AbstractLinkedProcessorSlot<?> protocolProcessor) {
|
||||
@@ -697,9 +499,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
public void addLast(AbstractLinkedProcessorSlot<?> protocolProcessor) {
|
||||
@@ -709,9 +508,6 @@ function hide_canvas() {
|
||||
end = protocolProcessor;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 调用头节点的 entry 方法
|
||||
|
||||
@Override
|
||||
@@ -735,13 +531,7 @@ function hide_canvas() {
|
||||
first.exit(context, resourceWrapper, count, args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h3>Sentinel 中的责任链模式</h3>
|
||||
@@ -759,9 +549,6 @@ function hide_canvas() {
|
||||
private static volatile Map<ResourceWrapper, ProcessorSlotChain> chainMap
|
||||
|
||||
= new HashMap<ResourceWrapper, ProcessorSlotChain>();
|
||||
|
||||
|
||||
|
||||
private Entry entryWithPriority(ResourceWrapper resourceWrapper, int count, boolean prioritized, Object... args)
|
||||
|
||||
throws BlockException {
|
||||
@@ -795,9 +582,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h3>Sentinel 的整体工作流程</h3>
|
||||
@@ -837,9 +621,6 @@ try {
|
||||
ContextUtil.exit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>上面代码我们分为五步分析:</p>
|
||||
@@ -867,9 +648,6 @@ try {
|
||||
return trueEnter(name, origin);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static Context trueEnter(String name, String origin) {
|
||||
|
||||
Context context = contextHolder.get();
|
||||
@@ -931,9 +709,6 @@ try {
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>ContextUtil 使用 ThreadLocal 存储当前调用链路的 Context,例如 Web MVC 应用中使用 Sentinel 的 Spring MVC 适配器,在接收到请求时,调用 ContextUtil#enter 方法会创建一个名为“sentinel_spring_web_context”的 Context,并且如果是首次创建还会为所有名为“sentinel_spring_web_context”的 Context 创建一个 EntranceNode。</p>
|
||||
@@ -983,9 +758,6 @@ try {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>如上代码所示,traceExceptionToNode 方法中首先获取当前资源的 ClusterNode,然后调用 ClusterNode#trace 方法记录异常。因为一个资源只创建一个 ProcessorSlotChain,一个 ProcessorSlotChain 只创建 ClusterBuilderSlot,一个 ClusterBuilderSlot 只创建一个 ClusterNode,所以一个资源对应一个 ClusterNode,这个 ClusterNode 就是用来统计一个资源的全局指标数据的,熔断降级与限流降级都有使用到这个 ClusterNode。</p>
|
||||
@@ -1009,9 +781,6 @@ try {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h4><strong>调用 Entry#exit 方法</strong></h4>
|
||||
@@ -1065,9 +834,6 @@ try {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>CtSph 在创建 CtEntry 时,将资源的 ProcessorSlotChain 赋值给了 CtEntry,所以在调用 CtEntry#exit 方法时,CtEntry 能够拿到当前资源的 ProcessorSlotChain,并调用 ProcessorSlotChain 的 exit 方法完成一次单向链表的 exit 方法调用。其过程与 ProcessorSlotChain 的一次 entry 方法的调用过程一样,因此不做分析。</p>
|
||||
@@ -1089,9 +855,6 @@ try {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>如果 Context.curEntry 为空,则说明所有 SphU#entry 都对应执行了一次 Entry#exit 方法,此时就可以将 Context 从 ThreadLocal 中移除。</p>
|
||||
@@ -1115,9 +878,6 @@ try {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1125,9 +885,6 @@ try {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||||
|
||||
</div>
|
||||
@@ -1143,17 +900,11 @@ try {
|
||||
<script>
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
|
||||
|
||||
function gtag() {
|
||||
|
||||
dataLayer.push(arguments);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-NPSEEVD756');
|
||||
@@ -1179,9 +930,6 @@ try {
|
||||
setCookie("lastPath", path)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setCookie(cname, cvalue) {
|
||||
|
||||
var d = new Date();
|
||||
@@ -1193,9 +941,6 @@ try {
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCookie(cname) {
|
||||
|
||||
var name = cname + "=";
|
||||
@@ -1213,12 +958,6 @@ try {
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user