深入解析: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是构建稳定可靠微服务系统的重要工具,掌握它有助于提升系统的容错能力和稳定性。

浙公网安备 33010602011771号