故障排查
本章汇总了 Sentinel 使用过程中的常见问题及其排查方法,帮助你快速定位和解决问题。
常见问题
1. 控制台看不到应用
问题描述:应用已启动并接入控制台,但在控制台的机器列表中看不到应用。
排查步骤:
1)检查依赖是否完整
确保项目中包含了传输模块依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.8</version>
</dependency>
2)检查启动参数
确认 JVM 参数配置正确:
-Dcsp.sentinel.dashboard.server=localhost:8080
如果是 Spring Cloud 应用,检查配置文件:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
3)检查端口冲突
查看客户端 API 端口是否被占用:
# Windows
netstat -ano | findstr 8719
# Linux/Mac
netstat -tlnp | grep 8719
如果端口被占用,指定其他端口:
-Dcsp.sentinel.api.port=8720
4)检查是否有访问量
Sentinel 是懒加载机制,需要有流量才会初始化。确保应用有请求进入。
5)检查日志
查看 Sentinel 日志文件:
# 日志位置
~/logs/csp/sentinel-record.log
~/logs/csp/sentinel-block.log
检查是否有连接错误:
# 正常日志示例
[Sentinel] INFO: Begin heartbeat to server localhost:8080
[Sentinel] INFO: [Heartbeat] Send heartbeat to localhost:8080 success
2. 规则配置后不生效
问题描述:在控制台配置规则后,规则没有生效。
排查步骤:
1)检查资源名称是否匹配
确认规则配置的资源名称与代码中定义的一致:
// 代码中定义的资源名
@SentinelResource(value = "getUser")
public User getUser(String id) { ... }
// 规则配置的资源名必须完全一致
rule.setResource("getUser"); // 不是 "getuser" 或 "GET:/getUser"
2)检查 Web 接口资源名
Web 接口的资源名默认包含 HTTP 方法前缀:
GET:/api/users
POST:/api/users
确保规则配置时使用了完整的资源名。
3)检查规则是否加载成功
通过 API 查看当前加载的规则:
# 查看流控规则
curl http://localhost:8719/getRules?type=flow
# 查看熔断规则
curl http://localhost:8719/getRules?type=degrade
4)检查规则配置正确性
// 检查阈值是否合理
rule.setCount(100); // 不是 0
// 检查限流模式
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 1=QPS, 0=线程数
5)检查版本兼容性
确保控制台版本与客户端版本兼容:
<!-- 客户端版本 -->
<sentinel.version>1.8.8</sentinel.version>
<!-- 控制台版本也应该使用 1.8.8 -->
3. 限流不生效
问题描述:配置了限流规则,但请求没有被限流。
排查步骤:
1)确认请求量是否超过阈值
确认实际的 QPS 是否真的超过了配置的阈值:
# 查看资源实时统计
curl http://localhost:8719/cnode?id=getUser
输出示例:
idx id thread pass blocked success total rt 1m-pass 1m-block 1m-all exception
1 getUser 5 100 0 100 100 10 6000 0 6000 0
blocked 列显示被限流的请求数。
2)检查是否正确捕获异常
// 错误:没有捕获 BlockException
Entry entry = SphU.entry("resource");
// 业务逻辑
entry.exit();
// 正确:捕获 BlockException
try {
Entry entry = SphU.entry("resource");
try {
// 业务逻辑
} finally {
entry.exit();
}
} catch (BlockException e) {
// 限流处理
System.out.println("被限流");
}
3)检查 Context 是否正确
// 错误:Context 使用不当
ContextUtil.enter("context1");
Entry entry1 = SphU.entry("resourceA");
ContextUtil.enter("context2"); // 无效,Context 只在入口设置有效
Entry entry2 = SphU.entry("resourceB");
4)检查链路限流配置
如果使用链路限流,确认入口资源名正确:
rule.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule.setRefResource("entrance1"); // 入口资源名
4. 熔断器不工作
问题描述:配置了熔断规则,但熔断器没有触发。
排查步骤:
1)检查最小请求数
确保统计时长内的请求数达到最小请求数:
rule.setMinRequestAmount(10); // 至少 10 个请求
rule.setStatIntervalMs(10000); // 统计时长 10 秒
2)检查异常是否正确记录
手动埋点时需要调用 Tracer.trace() 记录异常:
try {
entry = SphU.entry("resource");
// 业务逻辑
} catch (BusinessException e) {
Tracer.trace(e); // 必须调用,否则异常不会被统计
throw e;
} finally {
entry.exit();
}
3)检查慢调用阈值
慢调用比例模式需要设置慢调用临界 RT:
rule.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType());
rule.setCount(500); // 慢调用临界 RT,单位 ms
rule.setSlowRatioThreshold(0.5); // 慢调用比例阈值
4)查看熔断器状态
注册状态监听器观察熔断器状态变化:
EventObserverRegistry.getInstance().addStateChangeObserver("debug",
(prevState, newState, rule, snapshotValue) -> {
System.out.println("熔断器状态: " + prevState + " -> " + newState);
System.out.println("触发值: " + snapshotValue);
});
5. 热点参数限流不生效
问题描述:配置了热点参数规则,但限流没有生效。
排查步骤:
1)检查参数传递
确保在 entry 和 exit 时都传入了参数:
Entry entry = null;
try {
entry = SphU.entry("resource", EntryType.IN, 1, param1, param2);
// 业务逻辑
} finally {
if (entry != null) {
entry.exit(1, param1, param2); // 必须传入相同的参数
}
}
2)检查参数索引
参数索引从 0 开始:
rule.setParamIdx(0); // 第一个参数
3)检查参数类型
参数例外项只支持基本类型和字符串:
ParamFlowItem item = new ParamFlowItem();
item.setObject("vip_user"); // 字符串值
item.setClassType(String.class.getName()); // 类型
item.setCount(100);
4)检查依赖
确保引入了热点参数限流依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>1.8.8</version>
</dependency>
6. 内存占用过高
问题描述:应用内存占用异常升高。
排查步骤:
1)检查资源数量
资源数量过多会增加内存占用:
# 查看所有资源
curl http://localhost:8719/tree?type=root
2)检查热点参数基数
热点参数的不同值过多会占用大量内存:
// 如果参数值太多(如用户ID),考虑是否需要热点参数限流
rule.setParamIdx(0);
3)调整滑动窗口配置
// 减少滑动窗口格子数
SampleCountProperty.updateGlobalSampleCount(2); // 默认值
4)检查是否有资源泄漏
确保每个 entry 都正确 exit:
try {
entry = SphU.entry("resource");
// 业务逻辑
} finally {
if (entry != null) {
entry.exit(); // 必须在 finally 中执行
}
}
7. 性能问题
问题描述:接入 Sentinel 后应用响应变慢。
排查步骤:
1)检查规则数量
规则数量过多会影响性能:
// 查看规则数量
FlowRuleManager.getRules().size();
2)检查资源埋点粒度
过度细粒度的埋点会增加开销:
// 不推荐:每个小方法都埋点
@SentinelResource(value = "helper1")
public void helperMethod1() { ... }
// 推荐:只对关键接口埋点
@SentinelResource(value = "api:process")
public void process() {
helperMethod1();
helperMethod2();
}
3)检查滑动窗口精度
高精度滑动窗口会增加开销:
// 降低精度
SampleCountProperty.updateGlobalSampleCount(2); // 不是 10 或更高
4)检查集群限流延迟
如果使用集群限流,网络延迟可能影响性能:
// 检查请求超时配置
ClusterClientConfig config = new ClusterClientConfig();
config.setRequestTimeout(20); // 默认 20ms
8. 规则持久化问题
问题描述:应用重启后规则丢失。
排查步骤:
1)检查动态数据源配置
确保配置了动态规则源:
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
rule-type: flow
2)检查配置中心连通性
确保能够连接到配置中心:
# 检查 Nacos 连接
curl http://localhost:8848/nacos/v1/cs/configs?dataId=app-flow-rules&group=SENTINEL_GROUP
3)检查规则格式
确保规则的 JSON 格式正确:
[
{
"resource": "test",
"grade": 1,
"count": 10
}
]
日志分析
日志文件位置
Sentinel 日志默认存放在用户目录下:
~/logs/csp/
├── sentinel-record.log # 主日志
├── sentinel-block.log # 限流日志
├── ${app}-metrics.log.${date} # 指标日志
└── command.log # 命令日志
常见日志信息
正常启动:
[Sentinel] INFO: Sentinel log output to ...
[Sentinel] INFO: Application name: my-app
[Sentinel] INFO: Begin heartbeat to server localhost:8080
连接控制台失败:
[Sentinel] ERROR: [Heartbeat] Send heartbeat to localhost:8080 failed
规则加载:
[Sentinel] INFO: [FlowRuleManager] Flow rules loaded: 5
[Sentinel] INFO: [DegradeRuleManager] Degrade rules loaded: 3
限流触发:
[Sentinel] INFO: Block: resource=getUser, origin=appA, count=1
日志配置
可以通过 JVM 参数自定义日志配置:
# 日志目录
-Dcsp.sentinel.log.dir=/var/log/sentinel
# 日志文件名
-Dcsp.sentinel.log.filename.pid=true
# 是否输出到控制台
-Dcsp.sentinel.log.output.to.console=true
HTTP API 调试
Sentinel 提供了丰富的 HTTP API 用于调试:
查看实时状态
# 查看所有资源
curl http://localhost:8719/tree?type=root
# 查看特定资源
curl http://localhost:8719/cnode?id=getUser
# 查看调用来源统计
curl http://localhost:8719/origin?id=getUser
查看规则
# 查看流控规则
curl http://localhost:8719/getRules?type=flow
# 查看熔断规则
curl http://localhost:8719/getRules?type=degrade
# 查看系统规则
curl http://localhost:8719/getRules?type=system
# 查看热点规则
curl http://localhost:8719/getParamRules
动态修改规则
# 设置流控规则
curl -X POST "http://localhost:8719/setRules?type=flow" -d '[{"resource":"test","grade":1,"count":10}]'
# 设置熔断规则
curl -X POST "http://localhost:8719/setRules?type=degrade" -d '[{"resource":"test","grade":0,"count":500,"timeWindow":30}]'
其他调试接口
# 健康检查
curl http://localhost:8719/health
# 版本信息
curl http://localhost:8719/version
# 查看集群模式
curl http://localhost:8719/cluster/server/transportInfo
调试技巧
1. 开启调试日志
// 注册状态变化监听器
EventObserverRegistry.getInstance().addStateChangeObserver("debug",
(prevState, newState, rule, snapshotValue) -> {
log.debug("熔断器状态变化: {} -> {}, 规则={}, 触发值={}",
prevState, newState, rule.getResource(), snapshotValue);
});
2. 打印当前规则
// 打印当前所有规则
log.info("流控规则: {}", FlowRuleManager.getRules());
log.info("熔断规则: {}", DegradeRuleManager.getRules());
log.info("系统规则: {}", SystemRuleManager.getRules());
3. 监控资源调用
// 注册回调
StatisticSlotCallbackRegistry.addEntryCallback("debug", new ProcessorSlotEntryCallback<DefaultNode>() {
@Override
public void onPass(Context context, ResourceWrapper resource, DefaultNode param, int count, Object... args) {
log.debug("资源通过: {}", resource.getName());
}
@Override
public void onBlocked(BlockException ex, Context context, ResourceWrapper resource, DefaultNode param, int count, Object... args) {
log.warn("资源被阻止: {}, 异常: {}", resource.getName(), ex.getClass().getSimpleName());
}
});
4. 检查上下文
// 打印当前上下文信息
Context context = ContextUtil.getContext();
if (context != null) {
log.debug("上下文名称: {}", context.getName());
log.debug("调用来源: {}", context.getOrigin());
log.debug("入口节点: {}", context.getEntranceNode());
}
问题排查流程
当遇到问题时,建议按以下流程排查:
1. 确认问题现象
↓
2. 查看日志文件
↓
3. 使用 HTTP API 检查状态
↓
4. 检查配置是否正确
↓
5. 检查代码实现
↓
6. 查看官方文档和 FAQ
↓
7. 搜索 GitHub Issues
↓
8. 提交 Issue