Sentinel 的设计围绕“流量治理”展开,以下是其核心概念:
资源(Resource):
SphU.entry(resourceName)
)定义资源。规则(Rule):
Slot 链(Slot Chain):
上下文(Context):
指标(Metric):
流量控制(Flow Control):
熔断降级(Circuit Breaking):
热点参数限流:
系统自适应保护:
集群流量控制:
动态规则配置:
Sentinel 的架构分为核心模块和扩展模块,以下是主要组成部分:
核心库(sentinel-core):
适配模块:
@SentinelResource
)或拦截器简化集成。Dashboard:
数据源扩展:
传输模块:
集群流控模块:
Sentinel 的实现依赖多种算法,以下详细讲解其核心算法:
LeapArray
数据结构管理滑动窗口。LeapArray
是一个循环数组,每个元素是一个时间片(WindowWrap
)。AtomicLong
)更新,确保线程安全。代码示例(伪代码):
class LeapArray {
WindowWrap[] array; // 循环数组
int windowSize; // 时间片大小(如 100ms)
int interval; // 窗口总大小(如 1s)
// 获取当前时间片的统计数据
WindowWrap getCurrentWindow() {
long time = System.currentTimeMillis();
int idx = (int) ((time / windowSize) % array.length);
WindowWrap window = array[idx];
// 如果时间片过期,重置
if (window.time < time - interval) {
window.reset();
}
return window;
}
}
1/QPS
的时间间隔生成令牌。代码示例(伪代码):
class TokenBucket {
double rate; // 每秒令牌生成速率
double capacity; // 桶容量
double tokens; // 当前令牌数
long lastRefill; // 上次填充时间
boolean tryAcquire() {
refill(); // 填充令牌
if (tokens >= 1) {
tokens -= 1;
return true;
}
return false;
}
void refill() {
long now = System.currentTimeMillis();
double newTokens = (now - lastRefill) * rate / 1000;
tokens = Math.min(capacity, tokens + newTokens);
lastRefill = now;
}
}
代码示例(伪代码):
class LeakyBucket {
double targetQps; // 目标 QPS
double initialQps; // 初始 QPS
long warmupPeriod; // 冷启动时间
long startTime; // 开始时间
boolean allowRequest() {
long now = System.currentTimeMillis();
double currentQps = calculateCurrentQps(now);
// 基于当前 QPS 判断是否允许通过
return checkQps(currentQps);
}
double calculateCurrentQps(long now) {
if (now - startTime >= warmupPeriod) {
return targetQps;
}
return initialQps + (targetQps - initialQps) * (now - startTime) / warmupPeriod;
}
}
代码示例(伪代码):
class CircuitBreaker {
enum State { CLOSED, OPEN, HALF_OPEN }
State state = State.CLOSED;
long openTime; // 熔断开始时间
double errorRatioThreshold; // 异常比例阈值
int minRequestCount; // 最小请求数
boolean allowRequest() {
if (state == State.OPEN) {
if (System.currentTimeMillis() > openTime + recoveryTimeout) {
state = State.HALF_OPEN;
return true; // 允许尝试恢复
}
return false;
}
if (state == State.HALF_OPEN) {
return tryRecover();
}
// CLOSED 状态,检查是否需要熔断
if (shouldOpen()) {
state = State.OPEN;
openTime = System.currentTimeMillis();
return false;
}
return true;
}
boolean shouldOpen() {
Metric metric = getMetric();
if (metric.requestCount < minRequestCount) {
return false;
}
return metric.errorCount / metric.requestCount > errorRatioThreshold;
}
}
allowedQps = min(maxQps, maxQps * (1 - loadFactor))
。代码示例(伪代码):
class AdaptiveLimiter {
double maxQps; // 最大 QPS
double cpuThreshold; // CPU 使用率阈值
boolean allowRequest() {
double cpuUsage = getCpuUsage();
double loadFactor = Math.max(0, cpuUsage - cpuThreshold) / (1 - cpuThreshold);
double allowedQps = maxQps * (1 - loadFactor);
// 基于 allowedQps 判断是否允许通过
return checkQps(allowedQps);
}
}
以下是一个简单的 Sentinel 使用示例,展示如何定义资源并配置限流规则。
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import java.util.ArrayList;
import java.util.List;
public class SentinelDemo {
public static void main(String[] args) {
// 配置限流规则
initFlowRules();
// 模拟请求
for (int i = 0; i < 20; i++) {
try (Entry entry = SphU.entry("HelloWorld")) {
// 业务逻辑
System.out.println("Request passed: " + i);
} catch (BlockException e) {
// 被限流
System.out.println("Request blocked: " + i);
}
}
}
private static void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("HelloWorld"); // 资源名称
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 基于 QPS 限流
rule.setCount(10); // QPS 阈值
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
输出示例:
Request passed: 0
Request passed: 1
...
Request passed: 9
Request blocked: 10
Request blocked: 11
...
Sentinel 是一个功能强大、性能优异的流量治理中间件,适用于分布式系统的高可用保护。其核心算法(如滑动窗口、令牌桶、漏桶、熔断降级、系统自适应)提供了灵活且高效的流量控制能力。通过合理的配置和集成,Sentinel 可以显著提升系统的稳定性和可靠性。