今日学习笔记:Sentinel 核心原理与关键算法
一、Sentinel 对外部请求的感知机制
Sentinel 对请求的感知依赖于 Web 框架适配与拦截器机制,核心是通过自动装配实现请求链路的透明化监控,为后续流量控制提供数据基础。
- 实现基础:SPI 与 Spring Boot 自动装配
Sentinel 提供 sentinel-spring-webmvc-adapter 等适配模块,基于 Spring Boot 的 SPI 机制(META-INF/spring.factories) 实现自动配置,无需手动注入拦截器,降低集成成本。
- 启动流程
- Spring Boot 容器启动时,Sentinel 自动加载并注册配置类 SentinelWebAutoConfiguration(用户原表述中“config-auto configuration”修正为标准类名)。
- 该配置类向 Spring 容器注入 SentinelWebInterceptor(网络拦截器),拦截所有符合规则的 HTTP 请求(默认拦截 /* 路径,可通过配置自定义)。
- 请求处理逻辑
- 拦截器的 preHandle 方法(请求处理前执行)会提取请求关键信息:URL 路径(如 /api/user)、请求来源(serviceName)、HTTP 方法(GET/POST)等。
- 将提取的信息封装为 ResourceEntry 对象(Sentinel 中的“资源”载体,每个 ResourceEntry 对应一个可监控的请求节点),并将该资源的调用数据(如调用次数、耗时)上报至 Sentinel 核心引擎。
- 核心引擎基于 ResourceEntry 的数据感知请求链路,为后续的限流、熔断、降级规则提供“靶向监控”能力(仅针对已感知的资源生效规则)。
二、Sentinel 核心算法
Sentinel 的流量控制、熔断降级功能依赖三大核心算法,分别对应“实时统计”“匀速排队”“突发流量兼容”三类场景,覆盖不同业务需求。
- 滑动时间窗口算法(核心统计算法)
核心思想
基于 前缀和思想 实现实时流量统计:将“一段时间区间”(如1秒)划分为多个连续的“小格子”(如10个100ms的格子),每个格子存储该时间段内的请求数、QPS、异常数等指标;统计时通过“当前时间对应的格子数据 + 未过期格子数据总和”计算总流量,避免传统“固定时间窗口”的统计偏差(如1秒窗口在0:59和1:01的瞬时高流量无法识别)。
底层实现
- 数据存储:将时间窗口抽象为 MetricBucket 类(存储 pass/block/exception 等指标),用数组( MetricArray )存储多个 MetricBucket ,每个数组元素对应一个“小格子”(格子粒度可配置,粒度越细统计越精准,但内存消耗略高)。
- 初始化逻辑:首次有请求进入时,初始化时间窗口数组,确定每个格子的时间范围(如第1个格子对应 0-100ms,第2个对应 100-200ms)。
- 时钟回拨处理:若服务器时钟发生回拨(如窗口终止时间 < 当前时间),直接丢弃过期格子数据并创建新窗口,避免因时钟异常导致的统计错误(正常生产环境极少触发,属于容错机制)。
- 适用场景:所有需要实时统计流量的场景(如 QPS 限流、并发数控制),是 Sentinel 最基础的算法。
- 漏桶算法(匀速排队机制)
核心思想
模拟“漏桶倒水”过程:请求像“水流”一样进入漏桶,漏桶以 固定速率(如每秒100个请求)将请求“漏出”到业务系统;若请求进入速率超过漏桶漏出速率,多余请求会在桶内排队(或直接丢弃,取决于配置),确保业务系统接收的请求速率平稳,避免瞬时高负载。
处理逻辑
- 计算请求等待时间:根据“当前桶内排队请求数”和“漏出速率”,计算当前请求需等待的最小时间(如桶内有5个请求,漏出速率100个/秒,则需等待 5*10ms=50ms)。
- 等待与放行:若等待时间在“最大排队时间”(如100ms)内,请求会睡眠至等待时间结束后放行;若等待时间超出最大排队时间,直接放行(避免请求排队过久导致超时)。
- 超时拦截:校验“请求到达时间 + 等待时间”是否超过“请求超时时间”,若已超时则直接拦截(返回 block 信号),避免无效等待。
- 适用场景:要求请求严格匀速处理的场景(如数据库写入、第三方接口调用,避免瞬时请求压垮下游服务)。
- 令牌桶算法(缓存预热机制)
核心思想
模拟“令牌生成与消耗”过程:Sentinel 按 预设速率(可配置) 定时向“令牌桶”中放入令牌(如每秒生成100个令牌),请求必须从桶中获取1个令牌才能放行;若桶内无令牌,请求会被限流(返回降级/熔断信息)。同时支持“缓存预热(冷启动)”,避免服务刚启动时令牌生成过多导致的瞬时高负载。
处理逻辑
- 令牌生成:令牌桶有固定容量(如200个令牌),当桶内令牌数未达容量时,按“预热速率”生成令牌(预热阶段速率从低到高逐步提升,如初始50个/秒,10秒后升至100个/秒);当桶满时,新生成的令牌直接丢弃。
- 请求处理:请求到达时,先检查桶内是否有剩余令牌:
- 若有令牌:获取1个令牌,请求正常放行,并记录请求数据。
- 若无令牌:触发限流逻辑,返回降级响应(如默认提示“系统繁忙,请稍后再试”,可自定义降级页面)。
- 突发流量兼容:令牌桶的容量决定了最大突发流量处理能力(如桶容量200,当瞬时有200个请求时,可一次性消耗所有令牌,后续请求需等待新令牌生成)。
- 适用场景:允许一定突发流量的场景(如 API 网关、用户登录接口,既控制长期流量,又兼容短时间内的流量峰值)。