Interview preparation--SpringCloudSentinel

Sentinel
  • Sentinel是一个轻量级的流控架构,主要以流量为切入点,从流量控制,熔断,系统负载保护等多个维度来帮助用户保护服务的稳定性。

  • 与Hystrixx相比,Sentinel设计更简单,使用更方便灵活,能动态的修改限制规则

  • Sentinel的设计中资源定义和 规则配置,还有流控算法三者是分开的,我们可以通过Sentinel api先定义好资源埋点,然后需要的时候我们在实时的增加上流控规则。这种方式极大的增加了Sentinel的灵活性。

  • 官网定义:

    • Sentinel带来的性能损耗:在单机25W QPS 的时候才会有显著影响5%~10%,单机QPS不大可以忽略不计
  • Sentinel 提供两种埋点方式:

    • try-catch方式 (通过SphU.entry)通过这种方式做资源定义的时候,如果触发限流或者熔断,会抛异常BlockException
    • if-else 方式(通过SphUO.entry),当方法返回false的时候就是异常处理的时机
Sentinel 工作流程
  • Sentinel所有资源都对应资源名称 resourceName,资源创建方式有
    • 自动适配,比如定义的接口都会自动适配生成对应的资源
    • 通过SphU api手动创建
    • 通过@SentinelResource注解手动创建
  • 每创建一个资源都会创建一个Entry,同时也会跟随着创建一系列的功能插槽Slot,这些插槽默认创建7 个,每一个插槽职责不同,Sentinel通过这些插槽功能完成各种维度数据统计,以及限流,熔断操作。
Sentinel Node之间的关系
  • Sentinel 每对应一个资源都创建默认7个Slot,利用Slot的功能完成数据统计,限流实现
  • Sentinel数据统计过程中会根据资源的各个维度进行统计,并且存储在不同类型的Node中,其中每个Node存储的数据维度不同,有如下几种Node节点了类型

请添加图片描述

  • Node:Node节点根接口类,定义了Node节点应该具有的功能点
  • StatisticNode: 统计节点,用来完成数据统计
  • EntranceNode:入口节点,入口流量的容积,他说每一个Context的入口节点,用来统计当前Context的总体流量数据
  • DefultNode:默认节点,用于在Resource + Context维度来统计数据
  • ClusterNode :用于在Resource维度的同价数据,不区分Context

请添加图片描述

  • 如上图中
    • 每个Context对应一个EntranceNode,例如默认的每一个接口都有一个流量统计EntranceNode
    • 对应每一个source对应一个DefaultNode,例如在每个请求过程中,我们可以定义多个@SentinelResource注解的方式增加资源,例如有多个方法需要流控,并且他会在同一个接口触发,那就会导致一个Context中可能存在多个resource,因此会有多个DefaultNode
    • 在DefaultNode2中他可能是自定一的一个限流方法,他可能被接口A调用,也可能被接口B调用,那么流量信息久会分布在ContextA与ContextB中,因此对resource2的总资源统计久由ClusterNode2 完成,因此维度是Context + resource
Sentinel 加载入口
  • 因为Sentinel资源生成方式有三种,上面也介绍了,分别是Sphu.entry手动调用API,@SentinelResource 注解,系统自动生成调用链路生成
  • 其中第一点是不用分析的,他直接调用Sentinel的API来完成
  • 下面先说一下自动化生产的情况
自动生成连路资源方式 SentinelWebAutoConfiguration
  • 引入依赖spring-cloud-starter-alibaba-sentinel中,依托SpringBoot的自动装配原理,会先去加载META-INFO/services 下的配置文件,其中spring.factories中配置了部分需要加载的类的全限定名。其中和自动连路生产相关的类是SentinelWebAutoConfiguration
  • 在SentinelWebAutoConfiguration类定义中,他实现了WebMvcConfigurer,我们可以通过WebMvcConfigurer 来实现自定义拦截器
  • 我们通过实现自己的addInterceptors方法来对接口的PathPatterns 进行拦截,默认情况设置的是/**,也就是对所有接口进行拦截,并且生成资源

请添加图片描述

注解SentinelResource方式
  • 同样在spring-cloud-stater-alibaba-sentinel中依赖自动装配机制,在META-INFO/service路径下加载spring.factories,本次关键类是SentinelAutoConfiguration
  • 在SentinelAutoConfiguration中定义了一个sentinelResourceAspect方法,这个方法通过spring AOP的方式定了切点为 SentinelResource的注解,以及一个Around的增强逻辑,通过AOP的环绕通知来进行增强
  • 在增强方法中他同样也是通过SphU.entry来创建context,统计数据,并做流控等检查
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
  • 在entry的最终实现中,首先会获取一个Context,Context是每一个请求必备的一个对象,因为每个请求都会占用一个线程,并且绑定一个Context
  • 如果没有在线程中获取到,那么会生成一个默认的 sentinel_default_context,并放入当前线程中
  • 接着会执行lookProcessChain,这个方法是整个架构和核心方法,会在方法中构建一个处理链,这个处理链是一个单向链表结构,类似于Filter的链,
 ProcessorSlot<Object> lookProcessChain(ResourceWrapper resourceWrapper) 
  • 接着来看下如何生成这个处理链的。
  • 在lookProcessChain方法中,通过SlotChainBuilder 以及ProcessorSlot 类,分别通过SPI技术加载META-INFO/services中的接口全限定配置文件,然后由ServiceLoader实现类的加载。
  • 在ProcessorSlot中久定义来我们需要加载默认7个slot,并且有默认的顺序
com.alibaba.csp.sentinel.slots.nodeselector.NodeSelectorSlot
com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot
com.alibaba.csp.sentinel.slots.logger.LogSlot
com.alibaba.csp.sentinel.slots.statistic.StatisticSlot
com.alibaba.csp.sentinel.slots.block.authority.AuthoritySlot
com.alibaba.csp.sentinel.slots.system.SystemSlot
com.alibaba.csp.sentinel.slots.block.flow.FlowSlot
com.alibaba.csp.sentinel.slots.block.degrade.DegradeSlot
  • 在加载完7个默认Slot后,返回的是AbstractLinkedProcessorSlot<?>他事所有slot的抽象父类,他借鉴了链表的设计,每个对象中定义了一个next指针。最终形成了一个链表结构,如官网中图片
    请添加图片描述

  • 构建这个链表同时用了责任链模式,在这默认的7个Slot中,每一个的功能点都不同,并且都比较复杂,比如:数据统计,限流,降级,热点参数,系统降级等,如果都写在同一个类中,那么必然造成维护困难,而且耦合严重,

  • 在OOP思想中,让每个类职责明确,因此通过责任链模式让每一个功能解偶并且用一个单向链表的数据结构将他们串联起来。

每个slot功能
  • 如管网中描述,在每个Slot功能如下:
  • NodeSelectSlot:负责收集资源的路径,就是我们在SentinelWebAutoConfiguration中通过拦截器得到的资源数据,将数据收集并且形成一个树状结构,在控制台中生成的那个树状结构数据就是通过这个节点生成的
  • ClusterBuilderSlot:用于存储资源的统计信息,以及调用者信息,例如资源的RT,QPS,这个数据存储点就是ClusterNode节点
  • LogSlot :记录日志
  • StatisticSlot: 用于记录,统计不同维度的runtime指标监控,比如异常,超时类似这种
  • AuthoritySlot: 这个根据配置的黑白名单和调用信息,做了一个权限控制
  • SystemSlot :系统级别的流控,用来控制总流量的,在控制台可以设置规则
  • FlowSlot: 最核心的限流,通过预设的流控规则,以及前面各种Slot中的统计数据进行流控,滑动窗口算法的核心实现
  • DegradeSlot:熔断降级控制Slot,也是更具配置的熔断规则 ,并且依据StatisticSlot中统计的信息来最熔断降级。

请添加图片描述

滑动窗口算法核心
  • 滑动窗口算法实现首你依赖的就是数据统计了,必须精确的统计处每个滑动窗口样本窗口中的请求量。为之后配合配置流控信息作限流准备
  • Sentinel中为了实现滑动窗口计数,将滑动窗口模型抽象成留一个LeapArray 环形数组,其实就是官方提供的图片中的WindowLeapArray

在这里插入图片描述

// 环形数组
public abstract class LeapArray<T> {   
 // 样本窗口长度    
 protected int windowLengthInMs;    
 // 一个时间窗中包含的时间窗数量    
 protected int sampleCount;    
 // 时间窗长度    
 protected int intervalInMs;    
 private double intervalInSecond;     
 // 这个一个数组,元素为WindowWrap样本窗口    
 // 注意,这里的泛型 T 实际为 MetricBucket 类型   
  protected final AtomicReferenceArray<WindowWrap<T>> array;
   ......   }  
  • 具体统计流程,当请求过来,
    • 更具当前请求时间戳获取当前时间所在的样本窗口,就2个计算步骤
      • 计算当前时间在那个样本窗口(样本窗口下标): 当前时间/样本窗口长度
      • 计算具体索引,这个array就是装样本窗口的数组
    • 用如下图片案例说明

请添加图片描述

  • 如上图中描述的是第一个步骤,假设整个滑动窗口10t,分四个时间窗口,每个2.5t,如果当前请求的时间是9t ,的出样子本窗口。9t / 2.5t = 3.6 ,因为是从0 开始计数,所以应该取 3

请添加图片描述

  • 此处描述第二个步骤:当前下标为3 的样本窗口 % 样本窗口长度 = 具体索引

  • 具体值是 3%4 = 3 ,也就是在数组的第三个位置。

  • 用另外一个更大的值在此计算,假设当前请求时间是35t

    • 第一个步骤35t/2.5t = 14
    • 第二个步骤 14 %4 = 2
  • 整体算法就是首先更具情趣的时间计算从 0 开始 需要多少个时间窗口才能达到你所在的时间,比如需要14 个时间窗口,因为我时间轮分的是4个时间窗口,所以第二个步骤计算的是,需要滑动几次,才能到14 个窗口的地方,最终计算出数组下标。

  • 第三个步骤,计算样本窗口的起点时间 : 计算当前样本窗口的起点 当前时间点-(当前时间点%样本窗口长度)

请添加图片描述

  • 上图中,样本窗口25t,当前时间90t,带入公式:

    • 当前时间点 - (当前时间点 % 样本时间窗口长度)= 90 -(90%25) = 75
  • 第四个步骤,比较第三部计算出的样本时间窗口开始时间 75 与 第二步中得到的数组下标对应时间窗口开始时间

    • 如果第二步计算出的数组当前值为null,那么应该是当前请求是这个时间窗口的第一个请求,直接新建 WindowWrap 并且通过CAS方式放入LeapArray中
    • 如果第二个步骤计算出的数组开始时间 和第三部计算的时间一样,则直接返回当前数组元素并统计
    • 如果第二个计算出的数组开始时间, > 第三部计算出的时间, 说明样本窗口中的时间已近过时了,需要替换,(这里是时间轮用法,向后的时间轮片总是会替换最开始的时间轮片)

请添加图片描述

  • 流程如下下:

请添加图片描述

Sentinel服务熔断过程
  • 服务熔断有三种状态:
    • 熔断关闭状态(Closed):服务没有故障的时候,熔断所处的状态,对调用方的调用不做任何限制。
    • 熔断开启状态(Open):后续对改服务接口的调用不在经过网络,直接执行本地的fallback方法。
    • 半熔断状态(Half-Open):尝试恢复服务调用,允许有限流量调用改服务,并且对调用结果进行统计,如果成功率达到配置指定要求,则恢复熔断关闭,否则继续执行熔断开启状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《深入理解系统设计面试》是一本非常有用的系统设计面试指南。该指南深入讲解了系统设计的关键概念、原则和最佳实践。它适用于那些准备参加系统设计面试或想要提高系统设计技能的人群。 这本指南分为两部分。第一部分主要介绍了系统设计的基本概念和术语。它解释了系统设计面试的常见问题类型,并提供了解决这些问题的方法和技巧。此外,该指南还详细介绍了常用的系统设计模式和架构,让读者能够更好地理解和应用这些概念。 第二部分是一系列实际的面试问题和解答。这些问题覆盖了各种不同的系统设计场景,包括分布式系统、缓存、数据库设计、消息队列等等。每个问题都提供了详细的解答和相应的讨论,读者可以从中学习到如何有效地分析问题、提出解决方案以及权衡不同的设计选择。 整本书的风格非常实用和易懂。它通过清晰的说明、图表和示例来解释概念,让读者能够更好地理解和掌握内容。此外,每个问题都有详细的解答和讨论,帮助读者深入思考和理解系统设计的各个方面。 总之,《深入理解系统设计面试》是一本非常有价值的系统设计指南。它提供了全面的知识和实践经验,帮助读者掌握系统设计的核心概念和技巧,从而在面试或实际工作中取得成功。无论你是准备参加系统设计面试还是提升个人技能,这本书都会对你有很大的帮助。 ### 回答2: 《Grokking the System Design Interview》是一本关于系统设计面试的书籍,旨在帮助读者掌握系统设计的技巧和策略。这本书通过详细的案例分析和解答常见面试问题的方法,帮助读者建立起解决复杂系统设计问题的能力。 这本书首先介绍了系统设计面试的背景和重要性,强调了良好的系统设计能力在面试中的价值。然后,书中逐步介绍了解决系统设计问题的一般方法和步骤,包括需求分析、整体设计、数据库设计、缓存设计、分布式系统设计等方面。 《Grokking the System Design Interview》的亮点在于它通过真实世界的案例分析来解释不同的系统设计问题和解决方法。每个案例都包含了问题背景、需求、约束条件和解决方案。通过阅读这些案例,读者可以了解不同类型问题的思考方式和解决方案,并能够将这些方法应用到自己的系统设计问题中。 此外,书中还提供了一些常用的设计方案和优化技巧的讨论,例如使用缓存来提高系统性能、使用负载均衡来增加系统可扩展性等。这些技巧对于读者在面试中展示自己的技术能力和解决问题的能力非常有帮助。 总而言之,《Grokking the System Design Interview》是一本系统全面的系统设计面试指南,通过案例分析和实践经验,帮助读者掌握系统设计的核心原则和技巧。阅读这本书可以帮助读者在系统设计面试中脱颖而出,并取得成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值