likes
comments
collection
share

面试官 : 关于 Sentinel 你知道多少 ?

作者站长头像
站长
· 阅读数 32

👈👈👈 欢迎点赞收藏关注哟

一. 前言

这一篇就基于生产用法来看一下整个 Sentinel 的流程。并且来了解一下生产级的 Sentinel 有哪些关注点。

Sentinel 官方文档里面就很完善了,我尽量挑里面没有的说说 :

sentinelguard.io/zh-cn/docs/…

二. 宏观概念

2.1 基于应用

Sentinel 常见有2种形式 , 基于单机的手动配置模式和基于 Dashboard 的可视化配置模式 :

单机模式

依赖 :com.alibaba.csp:sentinel-core

public void test() throws InterruptedException {
    // S1 : 初始化 Rule 规则
    initFlowRules();
    while (true) {
        Entry entry = null;
        try {
            // S2 : 标注需要处理的 Resource 类型,和配置中的一一对应
            entry = entry("HelloWorld");
            System.out.println("OK.业务成功执行");
        } catch (BlockException e1) {
            System.out.println("ERROR.业务被阻塞!");
            Thread.sleep(300);
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }
}

private static void initFlowRules() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();

    // 定义 Rule 规则,这里基于 QPS ,每秒可以请求三次
    rule.setResource("HelloWorld");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setCount(3);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}
  • 在这套使用中我们可以进行扩展思考 :
    • 单机模式关注面是当前 Pod 节点,也就是说它没有上报的功能
    • 单机场景下只需要在 initFlowRules 环节中通过 FlowRuleManager.loadRules 就可以开启限流
    • 这类方式规则不能持久化,或者说现阶段好的持久化方式都需要定制
    • 不具备图形界面,没有可观测性,不能实时调节
    • 只需要引入一个小小的包就能实现自定义的拦截,相对其实很轻量级了

单机-升级版

  • 依赖 (在上述基础上): com.alibaba.csp:sentinel-annotation-aspectj

@Bean
public SentinelResourceAspect sentinelResourceAspect() {
    return new SentinelResourceAspect();
}

@SentinelResource(value="annotationSource")
public void test(){
    System.out.println("OK.业务成功执行");
}

  • 整体用法和上述一样,最大的区别在于基于注解实现
  • 核心功能还是基于 AOP 原理,只不过是在 AOP 里面帮忙操作了 Entry

集群-外部DataSource

因为默认情况下 Sentinel 都是内存保存的配置,基于初始化的配置进行的流程。

所以一般情况下,会自定义数据源,并且设置动态的处理。

这一块本期不深入,后续文章再细说。

Dashbaord 集群版

上面的一切问题都在于单机场景,没办法链接到集群,这里面就涉及到一个问题 :

  • 集群之间机器与机器的情况需要上报 -> 汇总 -> 分析 -> 下发
  • 那么就需要一个服务器来进行数据汇总
  • 需要具体的上报策略,因为每一个请求来了都上报肯定是不现实的,会影响到接口的性能
// S1 : 首先基于官方文档创建好 Dashboard
https://sentinelguard.io/zh-cn/docs/dashboard.html 


// S2 : 集成方式
- 依赖包 : com.alibaba.csp # sentinel-transport-simple-http
- 配置项 : 
    - -Dcsp.sentinel.dashboard.server=127.0.0.1:8080


好了 , 基础原理的使用到这里就结束了 , 下面开始概念性的学习 。

2.2 基于概念

基本概念也是文档里面直接就有的,不深入就做一些总结

  • 资源 : sentinel 中被保护的对象,可以是方法,接口,url 等等
  • Entry : Entry 标识一个资源的入口,通过 Entry 对资源进行保护
  • 规则 : 对资源的访问策略,包括流量,熔断,热点等
    • 流量控制规则 : 基于不同的模式对流量进行控制,可以直接拒绝 / 等待
    • 熔断降级规则 : 当达到异常比例的时候触发熔断
    • 系统保护规则 : 基于 CPU ,负载 ,整体 QPS ,线程数多个指标进行自适应的流控
    • 访问控制规则 : 资源的黑白名单控制 (Sentinel 做这个感觉定位上有的不符合)
    • 热点规则 : 对热点数据 (集成访问的,访问频繁的)进行针对性的流控

控制台 Dashboard 的作用是什么 ?

@ sentinelguard.io/zh-cn/docs/…

总结一下 , 控制台除了能实时监控,其他一大重要功能在于规则管理和推送,也就是说完全可以把 Dashboard 看成 Sentinel 的 Server 端。

Dashboard 本体默认是不支持数据持久化的,应用重启后配置就失效了,所以一般情况下我们会持久化 Sentinel 配置,具体见下文持久化的配置。

Sentinel 简单原理讲述

Sentinel 当触发资源入口后进入处理流程,其核心流程是在一个 Slot 链中进行的 ,Slot 链是 Sentinel 中的功能插槽,各自负责的功能不同。

包括用于存储的几个 : NodeSelectorSlot (存储是搜集资源路径),ClusterBuilderSlot (存储资源的统计信息以及调用者信息) 指标,StatisticSlot (用于记录 Runtime).

另外就是实际进行控制的 Slot 包括 : FlowSlot (用于流量控制),AuthoritySlot (用于黑白名单控制),DegradeSlot (熔断降级) 以及 SystemSlot (系统指标控制)。

当通过 DefaultProcessorSlotChain 链表触发执行这些 Slot 后,Slot 会调用到其各自的 Check 用于校验是否符合当前配置的策略 。

以 FlowSlot 为例 :

  • S1 : 首先通过 SphU # entry 触发资源入口处理
  • S2 : 通过一系列处理来到 DefaultProcessorSlotChain # entry 从而处理链表
  • S3 : 进入到 FlowSlot 来进行流量控制,由 Slot 中调用 Check
  • S4 : 进入 FlowRuleChecker 判断当前的流量情况是否满足规则
  • S5 : 满足则通过当前校验,不满足抛出 FlowException 被外部捕获进行处理

其他基础原理

每个功能点都能讲一下,但是这篇文章篇幅就会太长了,推荐直接看文档。

不想看的可以关注我,后续应该会推出基于生产的使用和原理讲解。

三. 生产级有哪些使用技巧

3.1 关于限流的方式

Sentinel 的限流主要是针对于入站流量限流,也就是说优先保护应用的稳定。

入站防护的方案很简单,添加注解或者定义资源入口就行。

但是很多场景下我们需要考虑出站流量,我们通常不能保证下游系统是否能承载足够的并发,这样的情况下就需要对出站流量进行控制,分为几个层级 :

  • 优先基于业务处理 : 例如通过MQ来消费的场景,最简单的就是减少 MQ 的消费线程,其次就是减少业务的处理线程。 通常不建议使用 Thread.sleep 的方案,那样其实资源并没有节省出来。
  • 合理区分渠道 : 不同的渠道接收的能力不一样,可以通过区分线程池处理 , 也不用在意精准的数值, 如果特殊的场景可以考虑上动态线程池
  • 能动态限流是最好的了 : 我们没有实现这种限流,但是这种限流属于比较理想 ,但是能实现则作用很大。能基于 Response 时间等参数实现限流最好。

3.2 关于持久化定制和配置

单纯的使用功能有时候并不能满足我们的需求,在一些场景里面我们就需要进行定制化操作了 :

@ sentinelguard.io/zh-cn/docs/…

扩展主要在 Dashboard 中进行,主要包括 : 规则 ,数据源

定义自定义的 Sentinel 规则链 :

  • S1 : 创建一个 Slot 对象 , 继承 AbstractLinkedProcessorSlot
  • S2 : 创建一个 ChainBuilder 对象 , 继承CustomSlotChainBuilder
  • S3 : SPI 注入 Builder 对象 (META-INF)
// S1 : 
public class TestAnalyseSlot  extends AbstractLinkedProcessorSlot<DefaultNode> {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count, boolean prioritized, Object... args) throws Throwable {
        logger.info("成功进入分析代码");
        logger.info("Current entry resource: {}", context.getCurEntry().getResourceWrapper().getName());
        fireEntry(context, resourceWrapper, param, count, prioritized, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
    }
}

// S2 : 
public class CustomSlotChainBuilder implements SlotChainBuilder {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public ProcessorSlotChain build() {
        logger.info("添加自定义限流链路");
        ProcessorSlotChain chain = new DefaultSlotChainBuilder().build();
        chain.addLast(new TestAnalyseSlot());
        return chain;
    }
}


// S3 : 在 Resource 下面创建 
- 文件路径 :META-INF/services/com.alibaba.csp.sentinel.slotchain.SlotChainBuilder
# 自定义 Slot
com.alibaba.csp.sentinel.demo.spring.webmvc.customer.CustomSlotChainBuilder

面试官 : 关于 Sentinel 你知道多少 ?

自定义 Resource :

@ sentinelguard.io/zh-cn/docs/…

大多数都已经有具体的实现方式了,包括 Nacos 和 File ,Zookeeper 等等。

另外要注意的是,这些配置信息是直接从 Client 到 DataSource ,而不是先到 dashboard 再到 DataSource。

所以 dashboard 只做了数据的汇总和配置的展示,并没有直接存储配置。

这一块比较多,放在这一篇不合适,下一篇单独讲!!

3.3 关于 Sentinel 的整合

Sentinel 在很多场景下都会配置其他的组件使用,例如 SpringGateway 等

配合 SpringGateway :Spring 网关是可以直接集成 Sentinel 的,分为2步

  • S1 :引入 Sentinel Cloud + Sentinel Gateway 依赖
  • S2 : 对网关进行配置,添加 Sentinel 拦截
<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>

spring:
  application:
    name: gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1     # nacos注册地址
      config:
        server-addr: 127.0.0.1     # 远程配置地址
    sentinel:
      transport:
        dashboard: localhost:8080       # sentinel注册地址
      # 直接建立心跳
      eager: true
      scg:
        # 限流后的响应配置
        fallback:
          content-type: application/json
          # 模式 response、redirect
          mode: response
          # 响应状态码
          response-status: 429
          # 响应信息
          response-body: 限流文案

具体的可以参考这篇文档 : blog.csdn.net/qq_43437874…

支持组件列表

对于一些特殊的组件,Sentinel 专门提供了 adapter 用于快速集成 :

  • 用于集成 gprc : sentinel-grpc-adapter
  • 用于集成 Dubbo : sentinel-dubbo-adapter

具体的看 sentinelguard.io/zh-cn/docs/…

3.4 关于 Sentinel 的性能问题

有的时候我们也要考虑 Sentinel 的性能问题, 比较3种常见场景的即可 :

循环数普通操作流控操作上报类型
3000008009001200
30000007521906210658

耗时主要是本地运行,没上监控,就本地打印时间取一个平均值,虽然不能说完全正确,但是大致也能看出时间曲线 :

正常流程 < 本地流控 < 上报流控。 所以当流控上报的时候确实是会产生一些资源的消耗的。

但是 !! 注意了,这里差异明显是由于我执行代码只是一句打印,所以差异会很明显。在300万操作情况下,也只是多耗时2秒左右,如果算上一些复杂的流控操作,我想这个耗时也是可以接受的。

另外由于执行的 dashboard 是在本机,所以这里没有把网络消耗考虑在内,这个才是大头。

至于资源占用上,一般都可以不考虑。在整个应用尺度上考虑这些小的占用意义不大。

总结

Sentinel 是我读的几个开源里面文档和源码都很清晰的,分包明确。所以读在这一块源码难度不高,可以尝试下。

Sentinel 还有2大重要的概念没在这一篇说,因为篇幅有限,但是会放在后续的计划中 :

  • Sentinel 自定义数据源的处理
  • Sentinel 上报和集群同步的流程

欢迎关注,这个月会全部捋清楚。

转载自:https://juejin.cn/post/7300102080903200779
评论
请登录