sentinel限流原理,腾讯T3亲自讲解

public abstract class Entry implements AutoCloseable {

private long createTime;

private Node curNode;

/**

  • {@link Node} of the specific origin, Usually the origin is the Service Consumer.

*/

private Node originNode;

private Throwable error; // 是否出现异常

protected ResourceWrapper resourceWrapper; // 资源信息

}

4、DefaultNode

Node默认实现类DefaultNode,该类还有一个子类EntranceNode;context有一个entranceNode属性,Entry中有一个curNode属性。

  • EntranceNode:该类的创建在初始化context时完成的,注意该类是针对context维度的,也就是一个context有且仅有一个EntranceNode。

  • DefaultNode:该类的创建是在NodeSelectorSlot.entry完成的,当不存在context.name对应的DefaultNode时会创建并保存在本地缓存;获取到context.name对应的DefaultNode后将该DefaultNode设置到当前context的curEntry.curNode属性,也就是说,在DefaultSelectorSlot中是一个context有且仅有一个DefaultNode。

看到这里,你是不是有疑问?为什么一个context有且仅有一个DefaultNode,我们的resouece跑哪去了呢,其实,这里的一个context有且仅有一个DefaultNode是在NodeSelectorSlot范围内,NodeSelectorSlot是ProcessorSlotChain中的一环,获取ProcessorSlotChain是根据Resource维度来的。总结为一句话就是:针对同一个Resource,多个context对应多个DefaultNode;针对不同Resource,(不管是否是同一个context)对应多个不同DefaultNode。这还没看明白 : ),好吧,我不bb了,上图吧:

DefaultNode结构如下:

public class DefaultNode extends StatisticNode {

private ResourceWrapper id;

/**

  • The list of all child nodes.

  • 子节点集合

*/

private volatile Set childList = new HashSet<>();

/**

  • Associated cluster node.

*/

private ClusterNode clusterNode;

}

一个Resouce只有一个clusterNode,多个defaultNode对应一个clusterNode,如果defaultNode.clusterNode为null,则在ClusterBuilderSlot.entry中会进行初始化。

同一个Resource,对应同一个ProcessorSlotChain,这块处理逻辑在lookProcessChain方法中,如下:

ProcessorSlot lookProcessChain(ResourceWrapper resourceWrapper) {

ProcessorSlotChain chain = chainMap.get(resourceWrapper);

if (chain == null) {

synchronized (LOCK) {

chain = chainMap.get(resourceWrapper);

if (chain == null) {

// Entry size limit.

if (chainMap.size() >= Constants.MAX_SLOT_CHAIN_SIZE) {

return null;

}

chain = SlotChainProvider.newSlotChain();

Map<ResourceWrapper, ProcessorSlotChain> newMap = newHashMap<ResourceWrapper, ProcessorSlotChain>(

chainMap.size() + 1);

newMap.putAll(chainMap);

newMap.put(resourceWrapper, chain);

chainMap = newMap;

}

}

}

return chain;

}

5、StatisticNode

StatisticNode中保存了资源的实时统计数据(基于滑动时间窗口机制),通过这些统计数据,sentinel才能进行限流、降级等一系列操作。StatisticNode属性如下:

public class StatisticNode implements Node {

/**

  • 秒级的滑动时间窗口(时间窗口单位500ms)

*/

private transient volatile Metric rollingCounterInSecond = newArrayMetric(SampleCountProperty.SAMPLE_COUNT,

IntervalProperty.INTERVAL);

/**

  • 分钟级的滑动时间窗口(时间窗口单位1s)

*/

private transient Metric rollingCounterInMinute = new ArrayMetric(60, 60 * 1000,false);

/**

  • The counter for thread count.

  • 线程个数用户触发线程数流控

*/

private LongAdder curThreadNum = new LongAdder();

}

public class ArrayMetric implements Metric {

private final LeapArray data;

}

public class MetricBucket {

// 保存统计值

private final LongAdder[] counters;

// 最小rt

private volatile long minRt;

}

其中MetricBucket.counters数组大小为MetricEvent枚举值的个数,每个枚举对应一个统计项,比如PASS表示通过个数,限流可根据通过的个数和设置的限流规则配置count大小比较,得出是否触发限流操作,所有枚举值如下:

public enum MetricEvent {

PASS, // Normal pass.

BLOCK, // Normal block.

需要zi料+ 绿色徽【vip1024b】

EXCEPTION,

SUCCESS,

RT,

OCCUPIED_PASS

}

6、Slot

Slot是sentinel中非常重要的概念,sentinel的工作流程就是围绕着一个个插槽所组成的插槽链来展开的。需要注意的是每个插槽都有自己的职责,他们各司其职完美的配合,通过一定的编排顺序,来达到最终的限流降级。默认的各个插槽之间的顺序是固定的,因为有的插槽需要依赖其他的插槽计算出来的结果才能进行工作。

sentinel通过SlotChainBuilder作为SPI接口,使得Slot Chain具备了扩展的能力。我们可以通过实现SlotChainBuilder接口加入自定义Slot并且定义编排各个slot之间的排序,从而可以给sentinel添加自定义的功能。

那SlotChain是在哪创建的呢?是在 CtSph.lookProcessChain() 方法中创建的,并且该方法会根据当前请求的资源先去一个静态的HashMap中获取,如果获取不到才会创建,创建后会保存到HashMap中。这就意味着,同一个资源会全局共享一个SlotChain。默认生成ProcessorSlotChain为:

// DefaultSlotChainBuilder

public ProcessorSlotChain build() {

ProcessorSlotChain chain = new DefaultProcessorSlotChain();

chain.addLast(new NodeSelectorSlot());

chain.addLast(new ClusterBuilderSlot());

chain.addLast(new LogSlot());

chain.addLast(new StatisticSlot());

chain.addLast(new SystemSlot());

chain.addLast(new AuthoritySlot());

chain.addLast(new FlowSlot());

chain.addLast(new DegradeSlot());

return chain;

六、springcloud如何使用sentinel


学习了sentinel核心概念之后,感觉整个人都不好了,真的是晦涩难懂,来个helloworld,轻松一下。

1、pom.xml

org.springframework.cloud

spring-cloud-starter-alibaba-sentinel

2、 controller

@RestController

public class TestController {

@GetMapping(value = “/hello”)

@SentinelResource(“hello”)

public String hello() {

return “Hello Sentinel”;

}

}

本次面试答案,以及收集到的大厂必问面试题分享:

字节跳动超高难度三面java程序员面经,大厂的面试都这么变态吗?

ibaba-sentinel

2、 controller

@RestController

public class TestController {

@GetMapping(value = “/hello”)

@SentinelResource(“hello”)

public String hello() {

return “Hello Sentinel”;

}

}

本次面试答案,以及收集到的大厂必问面试题分享:

[外链图片转存中…(img-a4Y3GEKk-1710366669488)]

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值