【Spring Cloud 8】熔断与限流 Sentinel,java 常见面试题
看到这里,你是不是有疑问?为什么一个 context 有且仅有一个 DefaultNode,我们的 resouece 跑哪去了呢,其实,这里的一个 context 有且仅有一个 DefaultNode 是在 NodeSelectorSlot 范围内,NodeSelectorSlot 是 ProcessorSlotChain 中的一环,获取 ProcessorS
lotChain 是根据 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<Node> childList = new HashSet<>();
/**
Associated cluster node.
*/
private ClusterNode clusterNode;
}
一个 Resouce 只有一个 clusterNode,多个 defaultNode 对应一个 clusterNode,如果 defaultNode.clusterNode 为 null,则在 ClusterBuilderSlot.entry 中会进行初始化。
同一个 Resource,对应同一个 ProcessorSlotChain,这块处理逻辑在 lookProcessChain 方法中,如下:
ProcessorSlot<Object> 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<MetricBucket> 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.
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
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、?controller
@RestController
public class TestController {
@GetMapping(value = "/hello")
@SentinelResource("hello")
public String hello() {
return "Hello Sentinel";
}
}
3、引入 dashboard
直接下载 sentinel-dashboard 的 jar 包。
默认是 8080 端口,在浏览器输入:localhost:8080,默认账号密码:sentinel:sentinel,看到控制台界面为部署成功。
4、application.properties
server.port=8088
spring.application.name=spring-cloud-alibaba-sentinel-demo
sentinel dashboard
spring.cloud.sentinel.transport.dashboard=localhost:8080
5、?启动 spring boot 项目,继续访问 localhost:8080,会看到如下界面
6、?使用 Sentinel 实现接口限流(在控制台)
7、测试
通过上面的配置,实现的是/hello 接口 qps 最大是 2,如果 qps 大于 2,则快速失败,配置完成,点击保存,我们快速刷新浏览器,会发现快速失败
七、总结
本文主要介绍了 Sentinel 的概念、特性、与 Hystrix 的区别、一些核心概念和与 SpringCloud 的简单整合。随着微服务的流行,服务和服务之间的稳定性变得越来越重要。??Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
每一篇博客都是一种经历,程序猿生涯的痕迹,知识改变命运,命运要由自己掌控,愿你游历半生,归来仍是少年。
欲速则不达,欲达则欲速!
评论