深入解析:Sentinel:全面学习笔记

目录

  • Sentinel概述
  • 核心概念
  • 环境搭建
  • 流量控制
  • 熔断降级
  • 系统自适应保护
  • 热点参数限流
  • 授权规则
  • 规则持久化
  • 监控面板
  • 集群流控
  • 实战案例
  • 最佳实践

Sentinel概述

Alibaba Sentinel是一款面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

核心特性
丰富的应用场景:承接了阿里巴巴近10年的双十一大促流量的核心场景
完备的实时监控:提供了实时的监控功能
广泛的开源生态:与Spring Cloud、Dubbo、gRPC等框架的整合
完善的SPI扩展:易于扩展的设计
多样化的规则配置:支持多种数据源

主要功能

┌─────────────────┐
│   应用服务      │
└─────────┬───────┘
│
┌─────────▼───────┐
│    Sentinel     │
├─────────────────┤
│ • 流量控制      │
│ • 熔断降级      │
│ • 系统保护      │
│ • 热点限流      │
│ • 授权控制      │
└─────────────────┘

流量控制:根据QPS、并发线程数等进行流量控制
熔断降级:当依赖的资源不稳定时,快速失败降级
系统负载保护:保护应用免受系统过载
热点参数限流:对热点参数进行特殊限流
实时监控:提供实时的资源运行状况

核心概念

资源(Resource)
资源是Sentinel的关键概念,可以是Java应用程序中的任何内容:

// 方法资源
@SentinelResource("getUserById")
public User getUserById(Long id) {
return userService.findById(id);
}
// URL资源(自动)
@GetMapping("/api/users/{id}")
public User getUser(@PathVariable Long id) {
return getUserById(id);
}
// 自定义资源
try (Entry entry = SphU.entry("customResource")) {
// 业务逻辑
return doSomeBusiness();
} catch (BlockException e) {
// 被限流/降级/系统保护的时候抛出的异常
return handleBlockException(e);
}

规则(Rule)
围绕资源的实时状态设定的规则:

流控规则(FlowRule):控制流量
降级规则(DegradeRule):熔断降级
系统规则(SystemRule):系统保护
热点规则(ParamFlowRule):热点参数限流
授权规则(AuthorityRule):访问控制

监控指标
Sentinel提供多维度的监控指标:

QPS:每秒查询率
RT:平均响应时间
并发线程数:正在处理的线程数
异常比例:异常请求所占比例
异常数量:每秒异常数量

环境搭建

依赖配置

<dependencies>
  <!-- Spring Boot Web -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
            <!-- Sentinel Core -->
              <dependency>
                <groupId>com.alibaba.csp</groupId>
                  <artifactId>sentinel-core</artifactId>
                    <version>1.8.6</version>
                      </dependency>
                        <!-- Sentinel Spring Boot Starter -->
                          <dependency>
                            <groupId>com.alibaba.cloud</groupId>
                              <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                                </dependency>
                                  <!-- Sentinel Dashboard通信 -->
                                    <dependency>
                                      <groupId>com.alibaba.csp</groupId>
                                        <artifactId>sentinel-transport-simple-http</artifactId>
                                          <version>1.8.6</version>
                                            </dependency>
                                              <!-- Sentinel数据源扩展 -->
                                                <dependency>
                                                  <groupId>com.alibaba.csp</groupId>
                                                    <artifactId>sentinel-datasource-nacos</artifactId>
                                                      <version>1.8.6</version>
                                                        </dependency>
                                                          <!-- Sentinel注解支持 -->
                                                            <dependency>
                                                              <groupId>com.alibaba.csp</groupId>
                                                                <artifactId>sentinel-annotation-aspectj</artifactId>
                                                                  <version>1.8.6</version>
                                                                    </dependency>
                                                                      <!-- Spring Cloud Alibaba Sentinel -->
                                                                        <dependency>
                                                                          <groupId>com.alibaba.cloud</groupId>
                                                                            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
                                                                              </dependency>
                                                                                </dependencies>

主启动类

@SpringBootApplication
@EnableSentinel
public class SentinelDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelDemoApplication.class, args);
}
}

基础配置

server:
port:8080
spring:
application:
name:sentinel-demo
cloud:
sentinel:
# 控制台地址
transport:
dashboard:localhost:8080
port:8719
# Web拦截配置
web-context-unify:true
# 数据源配置
datasource:
# 流控规则
flow:
nacos:
server-addr:localhost:8848
dataId:${spring.application.name}-flow-rules
groupId:SENTINEL_GROUP
rule-type:flow
# 降级规则
degrade:
nacos:
server-addr:localhost:8848
dataId:${spring.application.name}-degrade-rules
groupId:SENTINEL_GROUP
rule-type:degrade
# 系统规则
system:
nacos:
server-addr:localhost:8848
dataId:${spring.application.name}-system-rules
groupId:SENTINEL_GROUP
rule-type:system
# 配置规则文件路径
filter:
url-patterns:"/**"
enabled:true
# 熔断器配置
circuitbreaker:
rules:
-resource:"GET:/api/users/{id}"
count:5
grade:2# 异常比例
time-window:10
# 流控配置
flow:
cold-factor:3
# Nacos配置
nacos:
config:
server-addr:localhost:8848
# 日志配置
logging:
level:
com.alibaba.csp.sentinel:DEBUG
pattern:
console:"%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
# 监控配置
management:
endpoints:
web:
exposure:
include:"*"

Sentinel配置类

@Configuration
@Slf4j
publicclass SentinelConfig {
@PostConstruct
public void initSentinel() {
// 初始化流控规则
initFlowRules();
// 初始化降级规则
initDegradeRules();
// 初始化系统规则
initSystemRules();
// 初始化热点参数规则
initParamFlowRules();
// 初始化授权规则
initAuthorityRules();
}
private void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
  // 用户查询接口限流
  FlowRule rule1 = new FlowRule();
  rule1.setResource("GET:/api/users/{id}");
  rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
  rule1.setCount(10); // QPS不超过10
  rule1.setStrategy(RuleConstant.STRATEGY_DIRECT);
  rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
  rules.add(rule1);
  // 用户列表接口限流(预热模式)
  FlowRule rule2 = new FlowRule();
  rule2.setResource("GET:/api/users");
  rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
  rule2.setCount(20);
  rule2.setStrategy(RuleConstant.STRATEGY_DIRECT);
  rule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
  rule2.setWarmUpPeriodSec(10); // 预热10秒
  rules.add(rule2);
  FlowRuleManager.loadRules(rules);
  log.info("流控规则初始化完成");
  }
  private void initDegradeRules() {
  List<DegradeRule> rules = new ArrayList<>();
    // 基于异常比例的降级
    DegradeRule rule1 = new DegradeRule();
    rule1.setResource("userService");
    rule1.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
    rule1.setCount(0.5); // 异常比例50%
    rule1.setTimeWindow(10); // 熔断时长10秒
    rule1.setMinRequestAmount(5); // 最小请求数
    rules.add(rule1);
    // 基于响应时间的降级
    DegradeRule rule2 = new DegradeRule();
    rule2.setResource("orderService");
    rule2.setGrade(RuleConstant.DEGRADE_GRADE_RT);
    rule2.setCount(1000); // 响应时间1000ms
    rule2.setTimeWindow(15); // 熔断时长15秒
    rule2.setMinRequestAmount(5);
    rules.add(rule2);
    DegradeRuleManager.loadRules(rules);
    log.info("降级规则初始化完成");
    }
    private void initSystemRules() {
    List<SystemRule> rules = new ArrayList<>();
      // 系统负载保护
      SystemRule rule1 = new SystemRule();
      rule1.setHighestSystemLoad(8.0); // 最大系统负载
      rules.add(rule1);
      // CPU使用率保护
      SystemRule rule2 = new SystemRule();
      rule2.setHighestCpuUsage(0.8); // CPU使用率80%
      rules.add(rule2);
      // 平均响应时间保护
      SystemRule rule3 = new SystemRule();
      rule3.setAvgRt(1000); // 平均响应时间1000ms
      rules.add(rule3);
      SystemRuleManager.loadRules(rules);
      log.info("系统规则初始化完成");
      }
      private void initParamFlowRules() {
      List<ParamFlowRule> rules = new ArrayList<>();
        // 热点参数限流
        ParamFlowRule rule = new ParamFlowRule();
        rule.setResource("getUserById");
        rule.setParamIdx(0); // 第一个参数
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(5); // 单个热点参数QPS不超过5
        rule.setDurationInSec(1);
        // 特殊参数值配置
        List<ParamFlowItem> paramFlowItems = new ArrayList<>();
          ParamFlowItem item1 = new ParamFlowItem();
          item1.setObject("1"); // 用户ID为1
          item1.setClassType(String.class.getName());
          item1.setCount(10); // 特殊限制QPS为10
          paramFlowItems.add(item1);
          rule.setParamFlowItemList(paramFlowItems);
          rules.add(rule);
          ParamFlowRuleManager.loadRules(rules);
          log.info("热点参数规则初始化完成");
          }
          private void initAuthorityRules() {
          List<AuthorityRule> rules = new ArrayList<>();
            // 黑白名单控制
            AuthorityRule rule = new AuthorityRule();
            rule.setResource("adminAPI");
            rule.setStrategy(RuleConstant.AUTHORITY_WHITE); // 白名单
            rule.setLimitApp("admin,super-admin"); // 允许的应用
            rules.add(rule);
            AuthorityRuleManager.loadRules(rules);
            log.info("授权规则初始化完成");
            }
            }

流量控制

基本流控

@RestController
@RequestMapping("/api")
@Slf4j
publicclass UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
@SentinelResource(value = "getUserById",
blockHandler = "getUserByIdBlockHandler",
fallback = "getUserByIdFallback")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
  log.info("获取用户: {}", id);
  User user = userService.findById(id);
  return ResponseEntity.ok(user);
  }
  // 流控处理
  public ResponseEntity<User> getUserByIdBlockHandler(Long id, BlockException ex) {
    log.warn("用户查询被限流: id={}, exception={}", id, ex.getClass().getSimpleName());
    return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
    .body(createDefaultUser(id, "服务繁忙,请稍后重试"));
    }
    // 降级处理
    public ResponseEntity<User> getUserByIdFallback(Long id, Throwable ex) {
      log.error("用户查询异常降级: id={}", id, ex);
      return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
      .body(createDefaultUser(id, "服务暂不可用"));
      }
      @GetMapping("/users")
      @SentinelResource(value = "getUserList", blockHandler = "getUserListBlockHandler")
      public ResponseEntity<List<User>> getUserList(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size) {
        log.info("获取用户列表: page={}, size={}", page, size);
        List<User> users = userService.findAll(page, size);
          return ResponseEntity.ok(users);
          }
          public ResponseEntity<List<User>> getUserListBlockHandler(int page, int size, BlockException ex) {
            log.warn("用户列表查询被限流: page={}, size={}", page, size);
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
            .body(Collections.emptyList());
            }
            private User createDefaultUser(Long id, String message) {
            User user = new User();
            user.setId(id);
            user.setName("默认用户");
            user.setEmail("default@example.com");
            user.setRemark(message);
            return user;
            }
            }

编程式流控

@Service
@Slf4j
publicclass OrderService {
public Order createOrder(CreateOrderRequest request) {
Entry entry = null;
try {
// 手动埋点
entry = SphU.entry("createOrder");
// 业务逻辑
return doCreateOrder(request);
} catch (BlockException e) {
// 被流控
log.warn("订单创建被限流: {}", request.getUserId());
return createFallbackOrder(request);
} catch (Exception e) {
// 业务异常,统计到异常数中
Tracer.trace(e);
throw e;
} finally {
if (entry != null) {
entry.exit();
}
}
}
private Order doCreateOrder(CreateOrderRequest request) {
log.info("创建订单: {}", request);
// 模拟业务处理
if (Math.random() > 0.9) {
thrownew RuntimeException("订单创建失败");
}
Order order = new Order();
order.setId(System.currentTimeMillis());
order.setUserId(request.getUserId());
order.setStatus("CREATED");
return order;
}
private Order createFallbackOrder(CreateOrderRequest request) {
Order order = new Order();
order.setId(-1L);
order.setUserId(request.getUserId());
order.setStatus("FALLBACK");
order.setRemark("系统繁忙,订单将稍后处理");
return order;
}
}

动态流控规则

@Service
@Slf4j
publicclass FlowRuleService {
public void updateFlowRule(String resource, int qps) {
List<FlowRule> rules = FlowRuleManager.getRules()
  .stream()
  .filter(rule -> !rule.getResource().equals(resource))
  .collect(Collectors.toList());
  // 添加新规则
  FlowRule newRule = new FlowRule();
  newRule.setResource(resource);
  newRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
  newRule.setCount(qps);
  newRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
  newRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
  rules.add(newRule);
  FlowRuleManager.loadRules(rules);
  log.info("更新流控规则: resource={}, qps={}", resource, qps);
  }
  public void removeFlowRule(String resource) {
  List<FlowRule> rules = FlowRuleManager.getRules()
    .stream()
    .filter(rule -> !rule.getResource().equals(resource))
    .collect(Collectors.toList());
    FlowRuleManager.loadRules(rules);
    log.info("删除流控规则: resource={}", resource);
    }
    public List<FlowRule> getFlowRules() {
      returnnew ArrayList<>(FlowRuleManager.getRules());
        }
        }

熔断降级

基于异常比例的熔断

@Service
@Slf4j
publicclass PaymentService {
@SentinelResource(value = "processPayment",
blockHandler = "processPaymentBlockHandler",
fallback = "processPaymentFallback")
public Payment processPayment(PaymentRequest request) {
log.info("处理支付: {}", request);
// 模拟异常
if (Math.random() > 0.7) {
thrownew PaymentException("支付处理异常");
}
Payment payment = new Payment();
payment.setId(System.currentTimeMillis());
payment.setOrderId(request.getOrderId());
payment.setAmount(request.getAmount());
payment.setStatus("SUCCESS");
return payment;
}
public Payment processPaymentBlockHandler(PaymentRequest request, BlockException ex) {
log.warn("支付处理被熔断: orderId={}", request.getOrderId());
Payment payment = new Payment();
payment.setOrderId(request.getOrderId());
payment.setAmount(request.getAmount());
payment.setStatus("BLOCKED");
payment.setRemark("支付系统繁忙,请稍后重试");
return payment;
}
public Payment processPaymentFallback(PaymentRequest request, Throwable ex) {
log.error("支付处理异常降级: orderId={}", request.getOrderId(), ex);
Payment payment = new Payment();
payment.setOrderId(request.getOrderId());
payment.setAmount(request.getAmount());
payment.setStatus("FAILED");
payment.setRemark("支付系统异常,请联系客服");
return payment;
}
}

基于响应时间的熔断

@Service
@Slf4j
publicclass ExternalApiService {
@SentinelResource(value = "callExternalApi",
blockHandler = "callExternalApiBlockHandler",
fallback = "callExternalApiFallback")
public ApiResponse callExternalApi(ApiRequest request) {
log.info("调用外部API: {}", request);
// 模拟慢调用
try {
Thread.sleep((long) (Math.random() * 2000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 模拟异常
if (Math.random() > 0.8) {
thrownew RuntimeException("外部API调用失败");
}
ApiResponse response = new ApiResponse();
response.setCode(200);
response.setMessage("Success");
response.setData("API调用成功");
return response;
}
public ApiResponse callExternalApiBlockHandler(ApiRequest request, BlockException ex) {
log.warn("外部API调用被熔断: {}", request);
ApiResponse response = new ApiResponse();
response.setCode(503);
response.setMessage("Service Unavailable");
response.setData("外部服务暂不可用");
return response;
}
public ApiResponse callExternalApiFallback(ApiRequest request, Throwable ex) {
log.error("外部API调用异常: {}", request, ex);
ApiResponse response = new ApiResponse();
response.setCode(500);
response.setMessage("Internal Error");
response.setData("外部服务异常");
return response;
}
}

熔断器状态监听

@Component
@Slf4j
publicclass CircuitBreakerStateListener {
@PostConstruct
public void init() {
// 注册熔断器状态变化监听器
EventObserverRegistry.getInstance().addStateChangeObserver("logging",
(prevState, newState, rule, snapshotValue) -> {
log.info("熔断器状态变化: resource={}, {} -> {}, rule={}, snapshotValue={}",
rule.getResource(), prevState, newState, rule, snapshotValue);
// 发送告警通知
if (newState == State.OPEN) {
sendCircuitBreakerAlert(rule.getResource(), "熔断器打开");
} elseif (newState == State.CLOSED) {
sendCircuitBreakerAlert(rule.getResource(), "熔断器关闭");
}
});
}
private void sendCircuitBreakerAlert(String resource, String message) {
log.warn("熔断器告警: resource={}, message={}", resource, message);
// 实现告警发送逻辑,如发送邮件、短信、钉钉消息等
}
}

系统自适应保护

系统规则配置

@Component
@Slf4j
publicclass SystemProtectionConfig {
@PostConstruct
public void initSystemRules() {
List<SystemRule> rules = new ArrayList<>();
  // CPU使用率保护
  SystemRule cpuRule = new SystemRule();
  cpuRule.setHighestCpuUsage(0.8); // CPU使用率不超过80%
  rules.add(cpuRule);
  // 系统负载保护
  SystemRule loadRule = new SystemRule();
  loadRule.setHighestSystemLoad(8.0); // 系统负载不超过8.0
  rules.add(loadRule);
  // 平均响应时间保护
  SystemRule rtRule = new SystemRule();
  rtRule.setAvgRt(1000); // 平均响应时间不超过1000ms
  rules.add(rtRule);
  // 并发线程数保护
  SystemRule threadRule = new SystemRule();
  threadRule.setMaxThread(100); // 最大并发线程数100
  rules.add(threadRule);
  // 入口QPS保护
  SystemRule qpsRule = new SystemRule();
  qpsRule.setQps(1000); // 系统整体QPS不超过1000
  rules.add(qpsRule);
  SystemRuleManager.loadRules(rules);
  log.info("系统保护规则初始化完成");
  }
  }

系统指标监控

@Component
@Slf4j
publicclass SystemMetricsMonitor {
@Scheduled(fixedRate = 30000)
public void reportSystemMetrics() {
// 获取系统指标
double cpuUsage = Constants.ENTRY_NODE.avgRt();
double systemLoad = Constants.ENTRY_NODE.curThreadNum();
long avgRt = Constants.ENTRY_NODE.avgRt();
int threadCount = Constants.ENTRY_NODE.curThreadNum();
double qps = Constants.ENTRY_NODE.passQps();
log.info("系统指标监控: CPU使用率={:.2f}%, 系统负载={:.2f}, " +
"平均响应时间={}ms, 并发线程数={}, QPS={:.2f}",
cpuUsage * 100, systemLoad, avgRt, threadCount, qps);
// 检查是否需要告警
checkSystemAlerts(cpuUsage, systemLoad, avgRt, threadCount, qps);
}
private void checkSystemAlerts(double cpuUsage, double systemLoad,
long avgRt, int threadCount, double qps) {
if (cpuUsage > 0.85) {
log.warn("CPU使用率告警: {:.2f}%", cpuUsage * 100);
}
if (systemLoad > 10.0) {
log.warn("系统负载告警: {:.2f}", systemLoad);
}
if (avgRt > 1500) {
log.warn("响应时间告警: {}ms", avgRt);
}
if (threadCount > 120) {
log.warn("并发线程数告警: {}", threadCount);
}
if (qps > 1200) {
log.warn("QPS告警: {:.2f}", qps);
}
}
}

热点参数限流

热点参数配置

@RestController
@RequestMapping("/api")
@Slf4j
publicclass HotParamController {
@GetMapping("/products/{productId}")
@SentinelResource(value = "getProduct",
blockHandler = "getProductBlockHandler")
public ResponseEntity<Product> getProduct(@PathVariable String productId) {
  log.info("获取商品: {}", productId);
  Product product = productService.findById(productId);
  return ResponseEntity.ok(product);
  }
  public ResponseEntity<Product> getProductBlockHandler(String productId, BlockException ex) {
    log.warn("商品查询被热点限流: productId={}", productId);
    Product defaultProduct = new Product();
    defaultProduct.setId(productId);
    defaultProduct.setName("商品暂不可用");
    defaultProduct.setDescription("商品访问量过大,请稍后重试");
    return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(defaultProduct);
    }
    @GetMapping("/search")
    @SentinelResource(value = "searchProducts",
    blockHandler = "searchProductsBlockHandler")
    public ResponseEntity<List<Product>> searchProducts(
      @RequestParam String keyword,
      @RequestParam(defaultValue = "0") int page,
      @RequestParam(defaultValue = "10") int size) {
      log.info("搜索商品: keyword={}, page={}, size={}", keyword, page, size);
      List<Product> products = productService.search(keyword, page, size);
        return ResponseEntity.ok(products);
        }
        public ResponseEntity<List<Product>> searchProductsBlockHandler(
          String keyword, int page, int size, BlockException ex) {
          log.warn("商品搜索被热点限流: keyword={}", keyword);
          return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
          .body(Collections.emptyList());
          }
          }

动态热点规则管理

@Service
@Slf4j
publicclass HotParamRuleService {
public void addHotParamRule(String resource, int paramIndex, int threshold) {
List<ParamFlowRule> rules = new ArrayList<>(ParamFlowRuleManager.getRules());
  ParamFlowRule rule = new ParamFlowRule();
  rule.setResource(resource);
  rule.setParamIdx(paramIndex);
  rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
  rule.setCount(threshold);
  rule.setDurationInSec(1);
  rules.add(rule);
  ParamFlowRuleManager.loadRules(rules);
  log.info("添加热点参数规则: resource={}, paramIndex={}, threshold={}",
  resource, paramIndex, threshold);
  }
  public void addSpecialParamRule(String resource, int paramIndex,
  Object paramValue, int threshold) {
  List<ParamFlowRule> rules = new ArrayList<>(ParamFlowRuleManager.getRules());
    ParamFlowRule rule = new ParamFlowRule();
    rule.setResource(resource);
    rule.setParamIdx(paramIndex);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setCount(5); // 默认阈值
    rule.setDurationInSec(1);
    // 特殊参数配置
    List<ParamFlowItem> paramFlowItems = new ArrayList<>();
      ParamFlowItem item = new ParamFlowItem();
      item.setObject(paramValue.toString());
      item.setClassType(paramValue.getClass().getName());
      item.setCount(threshold);
      paramFlowItems.add(item);
      rule.setParamFlowItemList(paramFlowItems);
      rules.add(rule);
      ParamFlowRuleManager.loadRules(rules);
      log.info("添加特殊热点参数规则: resource={}, paramValue={}, threshold={}",
      resource, paramValue, threshold);
      }
      public List<ParamFlowRule> getHotParamRules() {
        returnnew ArrayList<>(ParamFlowRuleManager.getRules());
          }
          }

授权规则

黑白名单控制

@Component
@Slf4j
publicclass AuthorityConfig {
@PostConstruct
public void initAuthorityRules() {
List<AuthorityRule> rules = new ArrayList<>();
  // 管理员接口白名单
  AuthorityRule adminRule = new AuthorityRule();
  adminRule.setResource("adminAPI");
  adminRule.setStrategy(RuleConstant.AUTHORITY_WHITE);
  adminRule.setLimitApp("admin,super-admin");
  rules.add(adminRule);
  // 支付接口黑名单
  AuthorityRule paymentRule = new AuthorityRule();
  paymentRule.setResource("paymentAPI");
  paymentRule.setStrategy(RuleConstant.AUTHORITY_BLACK);
  paymentRule.setLimitApp("blacklisted-app");
  rules.add(paymentRule);
  AuthorityRuleManager.loadRules(rules);
  log.info("授权规则初始化完成");
  }
  }
  @Component
  publicclass RequestOriginParser implements com.alibaba.csp.sentinel.adapter.web.common.RequestOriginParser {
  @Override
  public String parseOrigin(HttpServletRequest request) {
  // 从请求头获取应用标识
  String appName = request.getHeader("X-App-Name");
  if (appName != null) {
  return appName;
  }
  // 从token中解析应用信息
  String token = request.getHeader("Authorization");
  if (token != null) {
  return parseAppFromToken(token);
  }
  // 从IP地址判断
  String remoteAddr = request.getRemoteAddr();
  return getAppByIp(remoteAddr);
  }
  private String parseAppFromToken(String token) {
  // 解析JWT token获取应用信息
  try {
  // 简化实现,实际应该解析JWT
  if (token.contains("admin")) {
  return"admin";
  } elseif (token.contains("user")) {
  return"user-app";
  }
  } catch (Exception e) {
  // 解析失败
  }
  return"unknown";
  }
  private String getAppByIp(String ip) {
  // 根据IP地址判断应用来源
  if (ip.startsWith("192.168.1.")) {
  return"internal-app";
  } elseif (ip.startsWith("10.0.")) {
  return"admin";
  }
  return"external-app";
  }
  }

权限拦截处理

@RestController
@RequestMapping("/api/admin")
@Slf4j
publicclass AdminController {
@GetMapping("/users")
@SentinelResource(value = "adminAPI",
blockHandler = "adminBlockHandler")
public ResponseEntity<List<User>> getAllUsers() {
  log.info("管理员获取所有用户");
  List<User> users = userService.findAll();
    return ResponseEntity.ok(users);
    }
    @DeleteMapping("/users/{id}")
    @SentinelResource(value = "adminAPI",
    blockHandler = "adminBlockHandler")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
      log.info("管理员删除用户: {}", id);
      userService.deleteById(id);
      return ResponseEntity.noContent().build();
      }
      public ResponseEntity<?> adminBlockHandler(BlockException ex) {
        log.warn("管理员接口访问被拒绝: {}", ex.getMessage());
        Map<String, Object> result = new HashMap<>();
          result.put("code", 403);
          result.put("message", "访问被拒绝,权限不足");
          result.put("timestamp", System.currentTimeMillis());
          return ResponseEntity.status(HttpStatus.FORBIDDEN).body(result);
          }
          }

规则持久化

Nacos数据源

spring:
cloud:
sentinel:
datasource:
# 流控规则
flow:
nacos:
server-addr:localhost:8848
dataId:sentinel-demo-flow-rules
groupId:SENTINEL_GROUP
rule-type:flow
# 自动刷新
namespace:public
# 降级规则
degrade:
nacos:
server-addr:localhost:8848
dataId:sentinel-demo-degrade-rules
groupId:SENTINEL_GROUP
rule-type:degrade
# 系统规则
system:
nacos:
server-addr:localhost:8848
dataId:sentinel-demo-system-rules
groupId:SENTINEL_GROUP
rule-type:system
# 授权规则
authority:
nacos:
server-addr:localhost:8848
dataId:sentinel-demo-authority-rules
groupId:SENTINEL_GROUP
rule-type:authority
# 热点参数规则
param-flow:
nacos:
server-addr:localhost:8848
dataId:sentinel-demo-param-flow-rules
groupId:SENTINEL_GROUP
rule-type:param-flow

自定义数据源

@Configuration
@Slf4j
publicclass SentinelDataSourceConfig {
@Bean
public FlowRuleDataSource flowRuleDataSource() {
String dataId = "sentinel-demo-flow-rules";
String groupId = "SENTINEL_GROUP";
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource =
  new NacosDataSource<>(nacosConfigService(), groupId, dataId,
    source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
      FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
      log.info("流控规则数据源注册完成");
      return flowRuleDataSource;
      }
      @Bean
      public DegradeRuleDataSource degradeRuleDataSource() {
      String dataId = "sentinel-demo-degrade-rules";
      String groupId = "SENTINEL_GROUP";
      ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource =
        new NacosDataSource<>(nacosConfigService(), groupId, dataId,
          source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {}));
            DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
            log.info("降级规则数据源注册完成");
            return degradeRuleDataSource;
            }
            private ConfigService nacosConfigService() {
            try {
            Properties properties = new Properties();
            properties.setProperty("serverAddr", "localhost:8848");
            properties.setProperty("namespace", "public");
            return NacosFactory.createConfigService(properties);
            } catch (Exception e) {
            thrownew RuntimeException("创建Nacos配置服务失败", e);
            }
            }
            }

规则同步管理

@Service
@Slf4j
publicclass SentinelRuleSyncService {
@Autowired
private ConfigService nacosConfigService;
public void syncFlowRulesToNacos(List<FlowRule> rules) {
  try {
  String dataId = "sentinel-demo-flow-rules";
  String groupId = "SENTINEL_GROUP";
  String content = JSON.toJSONString(rules, true);
  boolean result = nacosConfigService.publishConfig(dataId, groupId, content);
  if (result) {
  log.info("流控规则同步到Nacos成功");
  } else {
  log.error("流控规则同步到Nacos失败");
  }
  } catch (Exception e) {
  log.error("同步流控规则到Nacos异常", e);
  }
  }
  public void syncDegradeRulesToNacos(List<DegradeRule> rules) {
    try {
    String dataId = "sentinel-demo-degrade-rules";
    String groupId = "SENTINEL_GROUP";
    String content = JSON.toJSONString(rules, true);
    boolean result = nacosConfigService.publishConfig(dataId, groupId, content);
    if (result) {
    log.info("降级规则同步到Nacos成功");
    } else {
    log.error("降级规则同步到Nacos失败");
    }
    } catch (Exception e) {
    log.error("同步降级规则到Nacos异常", e);
    }
    }
    @EventListener
    public void handleRuleChange(RuleChangeEvent event) {
    log.info("检测到规则变化: type={}, action={}", event.getType(), event.getAction());
    switch (event.getType()) {
    case"flow":
    syncFlowRulesToNacos(FlowRuleManager.getRules());
    break;
    case"degrade":
    syncDegradeRulesToNacos(DegradeRuleManager.getRules());
    break;
    default:
    log.warn("未知的规则类型: {}", event.getType());
    }
    }
    }

监控面板

Dashboard配置
@Configuration
public class SentinelDashboardConfig {
@Bean
public ServletRegistrationBean<HttpServlet> sentinelApiServlet() {
  // 注册Sentinel API Servlet
  return new ServletRegistrationBean<>(
    new com.alibaba.csp.sentinel.adapter.servlet.CommonFilter(),
    "/*");
    }
    }

自定义监控指标

@Component
@Slf4j
publicclass SentinelMetricsCollector {
@Scheduled(fixedRate = 60000)
public void collectMetrics() {
// 收集资源指标
Map<String, ClusterNode> clusterNodeMap = ClusterBuilderSlot.getClusterNodeMap();
  for (Map.Entry<String, ClusterNode> entry : clusterNodeMap.entrySet()) {
    String resource = entry.getKey();
    ClusterNode node = entry.getValue();
    // 获取指标数据
    double passQps = node.passQps();
    double blockQps = node.blockQps();
    double totalQps = node.totalQps();
    double avgRt = node.avgRt();
    int curThreadNum = node.curThreadNum();
    log.info("资源指标 [{}]: 通过QPS={:.2f}, 阻塞QPS={:.2f}, 总QPS={:.2f}, " +
    "平均RT={:.2f}ms, 并发线程数={}",
    resource, passQps, blockQps, totalQps, avgRt, curThreadNum);
    // 发送到监控系统
    sendMetricsToMonitoring(resource, passQps, blockQps, totalQps, avgRt, curThreadNum);
    }
    }
    private void sendMetricsToMonitoring(String resource, double passQps, double blockQps,
    double totalQps, double avgRt, int curThreadNum) {
    // 发送指标到Prometheus、InfluxDB等监控系统
    log.debug("发送监控指标: resource={}", resource);
    }
    }

集群流控

集群流控配置

spring:
cloud:
sentinel:
# 集群流控配置
cluster:
# Token Server配置
server:
port:18730
# Token Client配置
client:
server-host:localhost
server-port:18730

Token Server配置

@Configuration
@ConditionalOnProperty(name = "sentinel.cluster.mode", havingValue = "server")
publicclass ClusterServerConfig {
@PostConstruct
public void initClusterServer() {
// 配置集群服务端
ClusterServerConfigManager.loadServerNamespaceSet(Collections.singleton("demo-namespace"));
// 启动Token Server
ClusterTokenServer tokenServer = new SentinelDefaultTokenServer();
tokenServer.start();
log.info("Sentinel集群Token Server启动完成");
}
}

Token Client配置

@Configuration
@ConditionalOnProperty(name = "sentinel.cluster.mode", havingValue = "client")
publicclass ClusterClientConfig {
@PostConstruct
public void initClusterClient() {
// 配置集群客户端
ClusterClientAssignConfig assignConfig = new ClusterClientAssignConfig();
assignConfig.setServerHost("localhost");
assignConfig.setServerPort(18730);
ClusterClientConfigManager.applyNewAssignConfig(assignConfig);
log.info("Sentinel集群Token Client配置完成");
}
}

实战案例

电商系统流量治理

@Service
@Slf4j
publicclass EcommerceFlowControlService {
@Autowired
private ProductService productService;
@Autowired
private OrderService orderService;
@Autowired
private PaymentService paymentService;
// 商品详情页(热点商品保护)
@SentinelResource(value = "getProductDetail",
blockHandler = "getProductDetailBlockHandler")
public ProductDetail getProductDetail(String productId) {
log.info("获取商品详情: {}", productId);
// 检查商品是否为热点商品
if (isHotProduct(productId)) {
// 热点商品使用缓存
return getProductDetailFromCache(productId);
}
return productService.getProductDetail(productId);
}
public ProductDetail getProductDetailBlockHandler(String productId, BlockException ex) {
log.warn("商品详情访问被限流: {}", productId);
// 返回简化的商品信息
return createSimplifiedProductDetail(productId);
}
// 下单接口(流控+降级)
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlockHandler",
fallback = "createOrderFallback")
public OrderResult createOrder(CreateOrderRequest request) {
log.info("创建订单: userId={}", request.getUserId());
// 检查用户限购
checkUserOrderLimit(request.getUserId());
// 创建订单
Order order = orderService.createOrder(request);
// 处理支付
Payment payment = null;
if (request.isImmediatePay()) {
payment = paymentService.processPayment(order);
}
returnnew OrderResult(order, payment);
}
public OrderResult createOrderBlockHandler(CreateOrderRequest request, BlockException ex) {
log.warn("订单创建被限流: userId={}", request.getUserId());
// 引导到排队页面
return OrderResult.createQueueResult(request.getUserId());
}
public OrderResult createOrderFallback(CreateOrderRequest request, Throwable ex) {
log.error("订单创建异常: userId={}", request.getUserId(), ex);
// 异步处理订单
asyncCreateOrder(request);
return OrderResult.createAsyncResult(request.getUserId());
}
// 支付接口(系统保护)
@SentinelResource(value = "processPayment",
blockHandler = "processPaymentBlockHandler")
public PaymentResult processPayment(PaymentRequest request) {
log.info("处理支付: orderId={}", request.getOrderId());
// 验证订单状态
Order order = orderService.getOrder(request.getOrderId());
if (!"CREATED".equals(order.getStatus())) {
thrownew PaymentException("订单状态不正确");
}
// 处理支付
Payment payment = paymentService.processPayment(request);
returnnew PaymentResult(payment);
}
public PaymentResult processPaymentBlockHandler(PaymentRequest request, BlockException ex) {
log.warn("支付处理被保护: orderId={}", request.getOrderId());
// 延迟支付
return PaymentResult.createDelayedResult(request.getOrderId());
}
private boolean isHotProduct(String productId) {
// 判断是否为热点商品
return productId.equals("1") || productId.equals("2");
}
private ProductDetail getProductDetailFromCache(String productId) {
// 从缓存获取商品详情
returnnew ProductDetail();
}
private ProductDetail createSimplifiedProductDetail(String productId) {
// 创建简化的商品详情
ProductDetail detail = new ProductDetail();
detail.setProductId(productId);
detail.setName("商品暂时不可用");
detail.setDescription("商品访问量过大,请稍后再试");
return detail;
}
private void checkUserOrderLimit(Long userId) {
// 检查用户下单限制
// 可以结合Redis实现用户维度的限流
}
@Async
public void asyncCreateOrder(CreateOrderRequest request) {
log.info("异步处理订单: userId={}", request.getUserId());
// 异步创建订单逻辑
}
}

最佳实践

1. 资源定义规范

// 好的资源命名
@SentinelResource("getUserById")           // 方法级别
@SentinelResource("UserService:findAll")   // 服务+方法
@SentinelResource("GET:/api/users/{id}")   // HTTP接口
// 避免的资源命名
@SentinelResource("method1")               // 不清晰
@SentinelResource("user")                  // 过于简单

2. 规则配置建议

# 流控规则配置建议
sentinel:
rules:
flow:
# 核心接口保守配置
-resource:"coreAPI"
grade:1# QPS
count:100
strategy:0# 直接拒绝
# 非核心接口可以更宽松
-resource:"nonCoreAPI"
grade:1
count:500
strategy:2# 排队等待
degrade:
# 外部依赖设置降级
-resource:"externalAPI"
grade:0# 响应时间
count:1000# 1秒
timeWindow:10

3. 监控告警策略

@Component
@Slf4j
publicclass SentinelAlertManager {
@EventListener
public void handleBlockEvent(BlockEvent event) {
String resource = event.getResource();
String rule = event.getRule();
// 根据资源重要程度设置不同告警级别
AlertLevel level = determineAlertLevel(resource);
switch (level) {
case CRITICAL:
sendCriticalAlert(resource, rule);
break;
case WARNING:
sendWarningAlert(resource, rule);
break;
case INFO:
log.info("资源被限流: resource={}, rule={}", resource, rule);
break;
}
}
private AlertLevel determineAlertLevel(String resource) {
if (resource.contains("payment") || resource.contains("order")) {
return AlertLevel.CRITICAL;
} elseif (resource.contains("user") || resource.contains("product")) {
return AlertLevel.WARNING;
}
return AlertLevel.INFO;
}
private void sendCriticalAlert(String resource, String rule) {
// 发送紧急告警
log.error("紧急告警: 核心资源被限流 - resource={}, rule={}", resource, rule);
}
private void sendWarningAlert(String resource, String rule) {
// 发送警告告警
log.warn("警告告警: 重要资源被限流 - resource={}, rule={}", resource, rule);
}
enum AlertLevel {
CRITICAL, WARNING, INFO
}
}

总结

Sentinel作为阿里巴巴开源的流量治理组件,提供了完整的流量防护解决方案:

流量控制:多维度的流量控制策略
熔断降级:快速失败和服务降级
系统保护:系统级别的自适应保护
热点限流:针对热点参数的精细化控制
实时监控:完善的监控和可视化
规则管理:灵活的规则配置和持久化

优势特点
生产验证:经过阿里巴巴大规模生产环境验证
功能丰富:涵盖流控、降级、系统保护等多个维度
易于使用:提供注解和编程两种使用方式
扩展性强:支持自定义数据源和规则
监控完善:实时监控和Dashboard

Sentinel是构建稳定可靠微服务系统的重要工具,掌握它有助于提升系统的容错能力和稳定性。

posted @ 2026-01-28 09:11  yangykaifa  阅读(0)  评论(0)    收藏  举报