ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Sentinel源码之基础概念

2022-05-21 10:34:33  阅读:173  来源: 互联网

标签:ContextUtil 概念 源码 exit Context Entry Sentinel entry


1.源码下载

下载地址:https://github.com/alibaba/Sentinel/tree/release-1.8

官网版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明

image

2.核心概念

Sentinel作为ali开源的一款轻量级流控框架,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。相比于Hystrix,Sentinel的设计更加简单,在 Sentinel中资源定义和规则配置是分离的,也就是说用户可以先通过Sentinel API给对应的业务逻辑定义资源(埋点),然后在需要的时候再配置规则,通过这种组合方式,极大的增加了Sentinel流控的灵活性。

引入Sentinel带来的性能损耗非常小。只有在业务单机量级超过25W QPS的时候才会有一些显著的影响(5% - 10% 左右),单机QPS不太大的时候损耗几乎可以忽略不计。

Sentinel提供两种埋点方式:

  • try-catch 方式(通过 SphU.entry(...)),用户在 catch 块中执行异常处理

  • if-else 方式(通过 SphO.entry(...)),当返回 false 时执行异常处理

3.工作流程

image

Sentinel 的核心骨架,将不同的 Slot 按照顺序串在一起(责任链模式),从而将不同的功能(限流、降级、系统保护)组合在一起。slot chain 其实可以分为两部分:统计数据构建部分(statistic)和判断部分(rule checking)。

在Sentinel里面,所有的资源都对应一个资源名称(resourceName),每次资源调用都会创建一个 Entry 对象。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 SphU API 显式创建。Entry 创建的时候,同时也会创建一系列功能插槽(slot chain),这些插槽有不同的职责,例如默认情况下会创建一下7个插槽:

NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;

ClusterBuilderSlot 则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据,对应簇点链路;

StatisticSlot 则用于记录、统计不同纬度的 runtime 指标监控信息;

FlowSlot 则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制,对应流控规则;

AuthoritySlot 则根据配置的黑白名单和调用来源信息,来做黑白名单控制,对应授权规则;

DegradeSlot 则通过统计信息以及预设的规则,来做熔断降级,对应熔断规则;

SystemSlot 则通过系统的状态,例如 load1 等,来控制总的入口流量,对应系统规则;

重要的概念:

slot chain:插槽

Node:根节点

Context:对资源操作时的上下文环境,每个资源操作(针对Resource进行的entry/exit)必须属于一个Context,如果程序中未指定Context,会创建name为"sentinel_default_context"的默认Context。一个Context生命周期内可能有多个资源操作,Context生命周期内的最后一个资源exit时会清理该Context,这也预示这真个Context生命周期的结束。

Entry:表示一次资源操作,内部会保存当前调用信息。在一个Context生命周期中多次资源操作,也就是对应多个Entry,这些Entry形成parent/child结构保存在Entry实例中

Sentinel 将 ProcessorSlot 作为 SPI 接口进行扩展,使得 Slot Chain 具备了扩展的能力。您可以自行加入自定义的 slot 并编排 slot 间的顺序,从而可以给 Sentinel 添加自定义的功能。

image

单个资源:

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;

public class ContextDemo {
 public void ContextUtil(){
     // 创建一个来自appA访问的Context
     // Context的名称为entrance1
     ContextUtil.enter("entrance1", "appA");
     // Entry就是一个资源操作对象
     Entry nodeA = null;
     try {
         // 获取资源resource1的entry
         nodeA = SphU.entry("resource1");
         // 如果代码走到这个位置,说明当前资源的请求通过了流控,可以继续进行相关业务处理
     } catch (BlockException e) {
         // 如果没有通过走到了这里,就表示请求被限流,这里进行降级操作
         e.printStackTrace();
     }finally {
         if (nodeA != null) {
             nodeA.exit();
         }
     }
     //释放Context
     ContextUtil.exit();
 }
}

多个资源:

public class ContextDemo {
 public void ContextUtil(){
     // 创建一个来自appA访问的Context
     // Context的名称为entrance1
     ContextUtil.enter("entrance1", "appA");
     // Entry就是一个资源操作对象
     Entry nodeA = null;
     Entry nodeB = null;
     try {
         // 获取资源resource1的entry
         nodeA = SphU.entry("resource1");
         // 如果代码走到这个位置,说明当前资源的请求通过了流控,可以继续进行相关业务处理

         //获取资源resource2的entry
         nodeB = SphU.entry("resource2");
         // 如果代码走到这个位置,说明当前资源的请求通过了流控,可以继续进行相关业务处理
     } catch (BlockException e) {
         // 如果没有通过走到了这里,就表示请求被限流,这里进行降级操作
         e.printStackTrace();
     }finally {
         if (nodeA != null) {
             nodeA.exit();
         }
         if (nodeB != null) {
             nodeB.exit();
         }
     }
     //释放Context
     ContextUtil.exit();
 }
}

4.Node之间的关系

一个Context中可以有多个Resource,每个资源都必须对应一个Entry

这张图的上半部分体现了Node之间的关系:

image

对应源码的关系:

image

从这张图片可以提取如下几个Node:

  • Node:接口,Sentinel 里面的各种种类的统计节点
  • StatisticNode:统计节点,是Node的实现类,用于完成数据统计
  • EntranceNode:DefaultNode的子类,入口节点,一个Context会有一个入口节点,用于统计当前Context的总体流量数据,统计维度为Context
  • DefaultNode:默认节点,用于统计一个resource在当前Context中的流量数据,DefaultNode持有指定的Context和指定的Resource的统计数据,意味着DefaultNode是以Context和Resource为维度的统计节点
  • ClusterNode:ClusterNode保存的是同一个Resource的相关的统计信息,是以Resource为维度的,不区分Context,这个是和DefaultNode的区别

Node 接口定义了一个 Node 类所需要提供的各项指标数据统计的相关功能,为外部屏蔽滑动窗口的存在。提供记录请求被拒绝、请求被放行、请求处理异常、请求处理成功的方法,以及获取当前时间窗口统计的请求总数、平均耗时等方法。

image

使用代码理解Node之间的关系

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.Sph;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;

public class ContextDemo {
 public void ContextUtil(){
     // 创建一个来自appA访问的Context
     // Context的名称为entrance1
     ContextUtil.enter("entrance1", "appA");
     // Entry就是一个资源操作对象
     Entry nodeA = null;
     Entry nodeB = null;
     try {
         // 获取资源resource的entry
         nodeA = SphU.entry("resource1");
         // 如果代码走到这个位置,就说明当前请求通过了流控,可以继续记性相关业务处理
         nodeB = SphU.entry("resource2");
         // 如果代码走到这个位置,就说明当前请求通过了流控,可以继续记性相关业务处理
     } catch (BlockException e) {
         // 如果没有通过走到了这里,就表示请求被限流,这里进行降级操作
         e.printStackTrace();
     } finally {
         if (nodeA != null) {
             nodeA.exit();
         }
         if (nodeB != null) {
             nodeB.exit();
         }
     }
     // 释放Context
     ContextUtil.exit();

    // ---------------------创建另一个来自appA访问的Context------------------------------

     // 创建一个来自appA访问的Context
     // Context的名称为entrance2
     ContextUtil.enter("entrance2", "appA");
     // Entry就是一个资源操作对象
     Entry nodeC = null;
     try {
         nodeB = SphU.entry("resource2");
         // 如果代码走到这个位置,就说明当前请求通过了流控,可以继续记性相关业务处理
         nodeC = SphU.entry("resource3");
     } catch (BlockException e) {
         // 如果没有通过走到了这里,就表示请求被限流,这里进行降级操作
         e.printStackTrace();
     } finally {
         if (nodeB != null) {
             nodeB.exit();
         }
         if (nodeC != null) {
             nodeC.exit();
         }
     }
     // 释放Context
     ContextUtil.exit();
 }
}

标签:ContextUtil,概念,源码,exit,Context,Entry,Sentinel,entry
来源: https://www.cnblogs.com/ZT-666/p/16294542.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有