Sentinel高级特性深度解析:扩展与集成实践

一、Slot责任链扩展机制

核心原理

Sentinel通过ProcessorSlotChain实现责任链模式,默认包含多个Slot(如NodeSelectorSlot、ClusterBuilderSlot等),按顺序处理请求:

图1

自定义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

实践建议

  1. 避免在Slot中执行耗时操作(如远程调用)
  2. 异常处理要确保不影响责任链继续执行
  3. 推荐继承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>() {};
        }
    }
}

高级实践建议

  1. 生产环境部署要点

    • 控制台建议开启认证:-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
  2. 性能优化技巧

    // 异步统计提升性能
    ContextUtil.enter("async-resource", "app");
    AsyncEntry entry = SphU.asyncEntry(resourceName);
    CompletableFuture.runAsync(() -> {
        try {
            // 业务逻辑
        } finally {
            entry.exit();
        }
    });
  3. 动态规则更新策略

    // 结合配置中心监听
    configService.addListener(dataId, group, new Listener() {
        public void receiveConfigInfo(String config) {
            List<FlowRule> rules = JSON.parseArray(config, FlowRule.class);
            FlowRuleManager.loadRules(rules);
        }
    });

通过以上扩展和集成方案,Sentinel可以灵活适应各种复杂业务场景,建议根据实际需求选择合适的扩展点进行深度定制。

评论已关闭