Sentinel高级特性解析:Slot扩展与SPI集成指南之二
Sentinel高级特性深度解析:扩展与集成实践
一、Slot责任链扩展机制
核心原理
Sentinel通过ProcessorSlotChain实现责任链模式,默认包含多个Slot(如NodeSelectorSlot、ClusterBuilderSlot等),按顺序处理请求:
自定义Slot实现
示例:请求日志记录Slot
public class LoggingSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
@Override
public void entry(Context context, ResourceWrapper resourceWrapper,
DefaultNode node, int count, Object... args) throws Throwable {
// 前置处理
System.out.printf("[%s] 访问资源 %s, 参数: %s%n",
LocalDateTime.now(),
resourceWrapper.getName(),
Arrays.toString(args));
// 触发下一个Slot
fireEntry(context, resourceWrapper, node, count, args);
}
@Override
public void exit(Context context, ResourceWrapper resourceWrapper,
int count, Object... args) {
// 后置处理
System.out.printf("[%s] 完成资源 %s 访问%n",
LocalDateTime.now(),
resourceWrapper.getName());
// 触发下一个Slot
fireExit(context, resourceWrapper, count, args);
}
}
注册自定义Slot
// 通过SPI机制注册
// 在resources/META-INF/services下创建文件:
// com.alibaba.csp.sentinel.slotchain.ProcessorSlot
com.your.package.LoggingSlot
实践建议
- 避免在Slot中执行耗时操作(如远程调用)
- 异常处理要确保不影响责任链继续执行
- 推荐继承
AbstractLinkedProcessorSlot
而非直接实现接口
二、SPI扩展点实战
1. InitFunc 初始化扩展
系统参数初始化示例
public class EnvInitFunc implements InitFunc {
@Override
public void init() {
// 设置应用类型(会影响统计维度)
System.setProperty("csp.sentinel.app.type", "1");
// 配置控制台地址
System.setProperty("csp.sentinel.dashboard.server", "localhost:8080");
}
}
2. RuleManager 规则管理扩展
自定义规则加载器
public class DatabaseRuleManager implements RuleManager<FlowRule> {
@Override
public List<FlowRule> loadRules() {
// 从数据库加载规则
return jdbcTemplate.query(
"SELECT resource, count FROM flow_rules",
(rs, rowNum) -> new FlowRule()
.setResource(rs.getString("resource"))
.setCount(rs.getDouble("count"))
);
}
@Override
public void register2Property(Property<List<FlowRule>> property) {
// 定时刷新规则
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
property.updateValue(loadRules());
}, 0, 30, TimeUnit.SECONDS);
}
}
SPI注册文件
# resources/META-INF/services/com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager
com.your.package.DatabaseRuleManager
三、监控与仪表盘高级用法
实时监控数据对接
自定义指标收集
public class CustomMetricsExporter implements MetricExtension {
@Override
public void addPass(String resource, int n, Object... args) {
Metrics.counter("sentinel.pass",
"resource", resource).increment(n);
}
@Override
public void addBlock(String resource, int n, String origin, BlockException ex) {
Metrics.counter("sentinel.block",
"resource", resource,
"rule", ex.getClass().getSimpleName()).increment(n);
}
}
Prometheus集成配置
# application.yml
management:
endpoints:
web:
exposure:
include: prometheus
metrics:
tags:
application: ${spring.application.name}
Grafana监控看板关键指标
- 实时QPS:
sum(rate(sentinel_pass_seconds_count[1m])) by (resource)
- 阻塞请求:
sum(rate(sentinel_block_seconds_count[1m])) by (resource)
- 平均RT:
sentinel_rt_sum / sentinel_rt_count
四、主流框架深度集成
1. Spring Cloud Alibaba适配
配置示例
spring:
cloud:
sentinel:
eager: true # 立即初始化
transport:
dashboard: localhost:8080
port: 8719
filter:
url-patterns: /**
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
ruleType: flow
Fallback全局处理
@RestControllerAdvice
public class SentinelFallbackHandler {
@ExceptionHandler(BlockException.class)
public ResponseEntity<String> handleBlock(BlockException ex) {
return ResponseEntity.status(429)
.body("请求被限流,请稍后重试");
}
}
2. Dubbo适配增强
Provider端保护
@DubboService
public class OrderServiceImpl implements OrderService {
@SentinelResource(
value = "OrderService:queryOrder",
fallback = "queryOrderFallback",
fallbackClass = OrderServiceFallback.class
)
public Order queryOrder(String orderId) {
// ...
}
}
Consumer端保护
@Reference(
version = "1.0.0",
check = false,
filter = "sentinel"
)
private OrderService orderService;
3. gRPC集成方案
拦截器实现
public class SentinelGrpcInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call,
Metadata headers,
ServerCallHandler<ReqT, RespT> next) {
String resourceName = call.getMethodDescriptor().getFullMethodName();
Entry entry = null;
try {
entry = SphU.entry(resourceName);
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(
next.startCall(call, headers)) {
@Override
public void onComplete() {
if (entry != null) {
entry.exit();
}
super.onComplete();
}
};
} catch (BlockException e) {
call.close(Status.RESOURCE_EXHAUSTED.withDescription(e.getMessage()), headers);
return new ServerCall.Listener<ReqT>() {};
}
}
}
高级实践建议
生产环境部署要点
- 控制台建议开启认证:
-Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=123456
- 使用独立集群模式时配置Token Server:
-Dcsp.sentinel.heartbeat.interval=10 -Dcsp.sentinel.heartbeat.client.ip=192.168.1.1
- 控制台建议开启认证:
性能优化技巧
// 异步统计提升性能 ContextUtil.enter("async-resource", "app"); AsyncEntry entry = SphU.asyncEntry(resourceName); CompletableFuture.runAsync(() -> { try { // 业务逻辑 } finally { entry.exit(); } });
动态规则更新策略
// 结合配置中心监听 configService.addListener(dataId, group, new Listener() { public void receiveConfigInfo(String config) { List<FlowRule> rules = JSON.parseArray(config, FlowRule.class); FlowRuleManager.loadRules(rules); } });
通过以上扩展和集成方案,Sentinel可以灵活适应各种复杂业务场景,建议根据实际需求选择合适的扩展点进行深度定制。
评论已关闭