规则持久化:Nacos、Apollo、Redis三种方案

三种方案对比 方案 实时性 高可用 运维成本 适用场景 Nacos 秒级 高 低 推荐,微服务首选 Apollo 秒级 高 中 已使用Apollo的项目 Redis 秒级 高 低 轻量级方案 文件 分钟级 低 高 不推荐生产使用 方案1:Nacos(推荐) 配置 spring: cloud: sentinel: datasource: flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP rule-type: flow namespace: dev Nacos中配置规则 [ { "resource": "orderCreate", "limitApp": "default", "grade": 1, "count": 1000, "strategy": 0, "controlBehavior": 0 } ] 优点 与Spring Cloud Alibaba深度集成 支持配置热更新 提供Web控制台 支持灰度发布 支持多环境(namespace) 方案2:Apollo 添加依赖 <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-apollo</artifactId> <version>1.8.6</version> </dependency> 配置 spring: cloud: sentinel: datasource: flow: apollo: namespace-name: application flow-rules-key: sentinel.flow.rules default-flow-rule-value: "[]" rule-type: flow Apollo中配置 Namespace: application Key: sentinel.flow.rules Value: ...

2025-11-20 · maneng

Gateway高级特性:自定义限流策略

自定义限流响应 方式1:自定义BlockExceptionHandler @Component public class CustomGatewayBlockHandler implements BlockRequestHandler { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) { Map<String, Object> result = new HashMap<>(); result.put("code", 429); result.put("message", "请求过于频繁,请稍后重试"); result.put("timestamp", System.currentTimeMillis()); if (ex instanceof FlowException) { result.put("reason", "触发限流"); } else if (ex instanceof DegradeException) { result.put("reason", "触发熔断"); } return ServerResponse .status(HttpStatus.TOO_MANY_REQUESTS) .contentType(MediaType.APPLICATION_JSON) .bodyValue(result); } } @Configuration public class GatewayConfig { @PostConstruct public void init() { GatewayCallbackManager.setBlockHandler(new CustomGatewayBlockHandler()); } } 方式2:根据路由返回不同响应 @Component public class RouteBasedBlockHandler implements BlockRequestHandler { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) { String routeId = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR) .toString(); Map<String, Object> result = new HashMap<>(); result.put("code", 429); // 根据不同路由返回不同消息 if ("order-service".equals(routeId)) { result.put("message", "订单服务繁忙,请稍后重试"); } else if ("product-service".equals(routeId)) { result.put("message", "商品服务繁忙,请稍后重试"); } else { result.put("message", "服务繁忙,请稍后重试"); } return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS) .contentType(MediaType.APPLICATION_JSON) .bodyValue(result); } } 自定义限流算法 实现KeyResolver // 1. 基于IP的限流 @Component public class IpKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just( exchange.getRequest().getRemoteAddress() .getAddress().getHostAddress() ); } } // 2. 基于用户ID的限流 @Component public class UserKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just( exchange.getRequest().getHeaders() .getFirst("X-User-Id") ); } } // 3. 基于API Key的限流 @Component public class ApiKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just( exchange.getRequest().getHeaders() .getFirst("X-API-Key") ); } } 配置使用 @Configuration public class GatewayRateLimiterConfig { @Bean public KeyResolver ipKeyResolver() { return new IpKeyResolver(); } @Bean public KeyResolver userKeyResolver() { return new UserKeyResolver(); } } // 在路由中使用 @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("order-service", r -> r.path("/api/order/**") .filters(f -> f .stripPrefix(2) .requestRateLimiter(c -> c .setRateLimiter(redisRateLimiter()) .setKeyResolver(ipKeyResolver()) ) ) .uri("lb://order-service")) .build(); } 自定义过滤器 实现全局限流过滤器 @Component @Order(-1) public class GlobalRateLimitFilter implements GlobalFilter { private final RedisTemplate<String, String> redisTemplate; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String ip = exchange.getRequest().getRemoteAddress() .getAddress().getHostAddress(); String key = "rate_limit:" + ip; Long count = redisTemplate.opsForValue().increment(key); if (count == 1) { redisTemplate.expire(key, 1, TimeUnit.SECONDS); } if (count > 100) { // 限流100 QPS exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } } 实现黑名单过滤器 @Component @Order(-2) public class BlackListFilter implements GlobalFilter { private final Set<String> blackList = new ConcurrentHashSet<>(); @PostConstruct public void init() { // 从Redis或数据库加载黑名单 blackList.add("192.168.1.100"); blackList.add("192.168.1.101"); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String ip = exchange.getRequest().getRemoteAddress() .getAddress().getHostAddress(); if (blackList.contains(ip)) { exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } public void addToBlackList(String ip) { blackList.add(ip); } public void removeFromBlackList(String ip) { blackList.remove(ip); } } 动态路由 基于Nacos的动态路由 @Component public class DynamicRouteService implements ApplicationEventPublisherAware { @Autowired private RouteDefinitionWriter routeDefinitionWriter; private ApplicationEventPublisher publisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; } public void add(RouteDefinition definition) { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); } public void update(RouteDefinition definition) { try { this.routeDefinitionWriter.delete(Mono.just(definition.getId())); } catch (Exception e) { // ignore } routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); } public void delete(String id) { this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); } } @Component public class NacosRouteListener { @Autowired private DynamicRouteService dynamicRouteService; @Autowired private NacosConfigManager nacosConfigManager; @PostConstruct public void init() throws Exception { String dataId = "gateway-routes"; String group = "DEFAULT_GROUP"; nacosConfigManager.getConfigService().addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { // 解析路由配置并更新 List<RouteDefinition> routes = JSON.parseArray(configInfo, RouteDefinition.class); routes.forEach(dynamicRouteService::update); } @Override public Executor getExecutor() { return null; } }); } } 完整实战案例 @Configuration public class GatewayAdvancedConfig { // 1. 自定义限流响应 @PostConstruct public void initBlockHandler() { GatewayCallbackManager.setBlockHandler(new CustomGatewayBlockHandler()); } // 2. 配置限流规则 @PostConstruct public void initGatewayRules() { Set<GatewayFlowRule> rules = new HashSet<>(); // 订单服务:QPS 1000 + Warm Up GatewayFlowRule orderRule = new GatewayFlowRule("order-service") .setCount(1000) .setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP) .setWarmUpPeriodSec(60); rules.add(orderRule); // 商品服务:QPS 2000 GatewayFlowRule productRule = new GatewayFlowRule("product-service") .setCount(2000); rules.add(productRule); // 秒杀API:QPS 5000 GatewayFlowRule seckillRule = new GatewayFlowRule("seckill_api") .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME) .setCount(5000); rules.add(seckillRule); GatewayRuleManager.loadRules(rules); } // 3. 配置API分组 @PostConstruct public void initCustomizedApis() { Set<ApiDefinition> definitions = new HashSet<>(); // 秒杀API分组 ApiDefinition seckillApi = new ApiDefinition("seckill_api") .setPredicateItems(new HashSet<ApiPredicateItem>() {{ add(new ApiPathPredicateItem().setPattern("/api/seckill/**") .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); }}); definitions.add(seckillApi); GatewayApiDefinitionManager.loadApiDefinitions(definitions); } } 总结 Gateway高级特性: ...

2025-11-20 · maneng

Dubbo服务流控:RPC调用的保护

Dubbo + Sentinel集成 添加依赖 <!-- Dubbo --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!-- Sentinel Dubbo适配器 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-apache-dubbo3-adapter</artifactId> <version>1.8.6</version> </dependency> 配置文件 dubbo: application: name: order-service registry: address: nacos://localhost:8848 protocol: name: dubbo port: 20880 consumer: timeout: 3000 check: false spring: cloud: sentinel: transport: dashboard: localhost:8080 服务提供者保护 定义接口 public interface ProductService { Product getProduct(Long id); List<Product> listProducts(int page, int size); } 实现类 @DubboService public class ProductServiceImpl implements ProductService { @Override @SentinelResource(value = "getProduct", blockHandler = "handleBlock") public Product getProduct(Long id) { return productDao.findById(id); } @Override @SentinelResource(value = "listProducts") public List<Product> listProducts(int page, int size) { return productDao.findAll(page, size); } public Product handleBlock(Long id, BlockException ex) { return Product.builder() .id(id) .name("商品服务限流") .build(); } } 配置限流规则 @Configuration public class ProviderSentinelConfig { @PostConstruct public void initRules() { List<FlowRule> rules = new ArrayList<>(); // 保护getProduct接口 FlowRule rule1 = new FlowRule(); rule1.setResource("getProduct"); rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); rule1.setCount(1000); rules.add(rule1); // 保护listProducts接口 FlowRule rule2 = new FlowRule(); rule2.setResource("listProducts"); rule2.setGrade(RuleConstant.FLOW_GRADE_QPS); rule2.setCount(500); rules.add(rule2); FlowRuleManager.loadRules(rules); } } 服务消费者保护 引用服务 @Service public class OrderService { @DubboReference private ProductService productService; @SentinelResource( value = "createOrder", fallback = "handleFallback" ) public Order createOrder(Long productId, int quantity) { // 调用Dubbo服务 Product product = productService.getProduct(productId); Order order = new Order(); order.setProductId(product.getId()); order.setQuantity(quantity); return orderDao.save(order); } public Order handleFallback(Long productId, int quantity, Throwable ex) { log.error("订单创建失败", ex); throw new BusinessException("商品服务不可用"); } } 配置熔断规则 @Configuration public class ConsumerSentinelConfig { @PostConstruct public void initRules() { List<DegradeRule> rules = new ArrayList<>(); DegradeRule rule = new DegradeRule(); rule.setResource("com.example.ProductService:getProduct(java.lang.Long)"); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); rule.setCount(1000); // RT > 1秒 rule.setSlowRatioThreshold(0.5); rule.setTimeWindow(10); rules.add(rule); DegradeRuleManager.loadRules(rules); } } 基于来源限流 场景:不同消费者不同限流 // 提供者配置 FlowRule rule = new FlowRule(); rule.setResource("getProduct"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setCount(100); rule.setLimitApp("order-service"); // 只对订单服务限流100 自定义来源解析 public class DubboOriginParser implements RequestOriginParser { @Override public String parseOrigin(HttpServletRequest request) { // 从Dubbo上下文获取调用方应用名 String application = RpcContext.getContext() .getAttachment("application"); return application != null ? application : "unknown"; } } Dubbo Filter实现 Sentinel通过Dubbo Filter自动拦截,资源名格式: ...

2025-11-20 · maneng

Spring Cloud Alibaba深度集成

微服务架构整体方案 ┌─────────────┐ │ Nacos │ ← 服务注册、配置中心 └─────────────┘ ↓ ┌─────────────┐ │ Gateway │ ← 网关(Sentinel限流) └─────────────┘ ↓ ┌─────────────┐ │ 订单服务 │ ← Sentinel流控、熔断 └─────────────┘ ↓ ┌─────────────┐ │ 商品服务 │ ← Sentinel流控、熔断 └─────────────┘ 完整依赖配置 <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2022.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- Nacos服务发现 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- Nacos配置中心 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- Sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- OpenFeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- LoadBalancer --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> Nacos + Sentinel配置 spring: application: name: order-service cloud: # Nacos配置 nacos: discovery: server-addr: localhost:8848 namespace: dev config: server-addr: localhost:8848 namespace: dev file-extension: yml # Sentinel配置 sentinel: transport: dashboard: localhost:8080 datasource: flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP rule-type: flow namespace: dev degrade: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-degrade-rules groupId: SENTINEL_GROUP rule-type: degrade namespace: dev # Feign配置 feign: sentinel: enabled: true client: config: default: connectTimeout: 5000 readTimeout: 5000 服务间调用保护 订单服务调用商品服务 @FeignClient( name = "product-service", fallback = ProductServiceFallback.class, fallbackFactory = ProductServiceFallbackFactory.class ) public interface ProductService { @GetMapping("/product/{id}") Product getProduct(@PathVariable Long id); } // Fallback实现 @Component public class ProductServiceFallback implements ProductService { @Override public Product getProduct(Long id) { return Product.builder() .id(id) .name("商品服务暂时不可用") .price(0.0) .build(); } } // FallbackFactory(可以获取异常信息) @Component public class ProductServiceFallbackFactory implements FallbackFactory<ProductService> { @Override public ProductService create(Throwable cause) { return new ProductService() { @Override public Product getProduct(Long id) { log.error("调用商品服务失败:{}", cause.getMessage()); return Product.builder() .id(id) .name("商品服务异常:" + cause.getMessage()) .build(); } }; } } 链路限流 场景:多个接口调用同一个服务 @Service public class OrderService { @Autowired private ProductService productService; // 接口1:创建订单 @SentinelResource(value = "createOrder") public Order createOrder(Long productId) { // 调用商品服务 getProductInfo(productId); return new Order(); } // 接口2:查询订单 @SentinelResource(value = "queryOrder") public Order queryOrder(Long orderId) { Order order = orderDao.findById(orderId); // 调用商品服务 getProductInfo(order.getProductId()); return order; } // 公共方法:获取商品信息 @SentinelResource(value = "getProductInfo", blockHandler = "handleBlock") private Product getProductInfo(Long productId) { return productService.getProduct(productId); } private Product handleBlock(Long productId, BlockException ex) { return Product.builder().id(productId).name("商品信息获取受限").build(); } } 配置链路限流 FlowRule rule = new FlowRule(); rule.setResource("getProductInfo"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setCount(100); rule.setStrategy(RuleConstant.STRATEGY_CHAIN); rule.setRefResource("createOrder"); // 只对createOrder链路限流 FlowRuleManager.loadRules(Collections.singletonList(rule)); 服务熔断配置 # 在Nacos中配置 # order-service-degrade-rules [ { "resource": "product-service", "grade": 0, "count": 1000, "timeWindow": 10, "minRequestAmount": 5, "statIntervalMs": 10000, "slowRatioThreshold": 0.5 }, { "resource": "inventory-service", "grade": 1, "count": 0.3, "timeWindow": 10, "minRequestAmount": 5, "statIntervalMs": 10000 } ] Gateway集成 spring: cloud: gateway: routes: - id: order-service uri: lb://order-service predicates: - Path=/api/order/** filters: - StripPrefix=2 sentinel: filter: enabled: false # 禁用默认过滤器 scg: fallback: mode: response response-status: 429 response-body: '{"code":429,"message":"请求过于频繁"}' 监控集成 暴露监控端点 management: endpoints: web: exposure: include: '*' endpoint: sentinel: enabled: true Prometheus集成 <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> @Configuration public class SentinelMetricsConfig { @PostConstruct public void init() { // 启用Sentinel指标导出 MetricRegistry.getMetricRegistry() .addMetricProvider(new SentinelMetricProvider()); } } 完整微服务实战 订单服务 @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } @RestController @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @PostMapping("/create") @SentinelResource(value = "orderCreateApi", blockHandler = "handleBlock") public Result createOrder(@RequestBody OrderDTO dto) { Order order = orderService.createOrder(dto); return Result.success(order); } public Result handleBlock(OrderDTO dto, BlockException ex) { return Result.error(429, "订单创建繁忙"); } } @Service public class OrderService { @Autowired private ProductService productService; @Autowired private InventoryService inventoryService; @SentinelResource(value = "createOrder", fallback = "handleFallback") @Transactional public Order createOrder(OrderDTO dto) { // 1. 检查商品 Product product = productService.getProduct(dto.getProductId()); // 2. 检查库存 boolean hasStock = inventoryService.checkStock(dto.getProductId(), dto.getQuantity()); if (!hasStock) { throw new BusinessException("库存不足"); } // 3. 扣减库存 inventoryService.deductStock(dto.getProductId(), dto.getQuantity()); // 4. 创建订单 Order order = new Order(); order.setProductId(product.getId()); order.setQuantity(dto.getQuantity()); order.setAmount(product.getPrice() * dto.getQuantity()); return orderDao.save(order); } public Order handleFallback(OrderDTO dto, Throwable ex) { log.error("订单创建失败", ex); throw new BusinessException("系统繁忙,请稍后重试"); } } 总结 Spring Cloud Alibaba + Sentinel集成要点: ...

2025-11-20 · maneng

Spring Boot集成最佳实践

Spring Boot Starter快速集成 添加依赖 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2022.0.0.0</version> </dependency> 配置文件 spring: application: name: order-service cloud: sentinel: transport: dashboard: localhost:8080 port: 8719 eager: true # 启动时立即初始化 # Web限流 filter: enabled: true url-patterns: /** # 数据源配置 datasource: flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP rule-type: flow @SentinelResource注解使用 基础用法 @Service public class OrderService { @SentinelResource( value = "createOrder", blockHandler = "handleBlock", fallback = "handleFallback" ) public Order createOrder(OrderDTO dto) { return orderDao.save(dto); } // 限流/熔断处理 public Order handleBlock(OrderDTO dto, BlockException ex) { throw new BusinessException("系统繁忙,请稍后重试"); } // 业务异常处理 public Order handleFallback(OrderDTO dto, Throwable ex) { log.error("创建订单失败", ex); throw new BusinessException("订单创建失败"); } } 异常类分离 public class OrderBlockHandler { public static Order handleBlock(OrderDTO dto, BlockException ex) { return Order.builder().status("BLOCKED").build(); } } public class OrderFallback { public static Order handleFallback(OrderDTO dto, Throwable ex) { return Order.builder().status("FALLBACK").build(); } } @Service public class OrderService { @SentinelResource( value = "createOrder", blockHandlerClass = OrderBlockHandler.class, blockHandler = "handleBlock", fallbackClass = OrderFallback.class, fallback = "handleFallback" ) public Order createOrder(OrderDTO dto) { return orderDao.save(dto); } } RestTemplate集成 @Configuration public class RestTemplateConfig { @Bean @SentinelRestTemplate( blockHandler = "handleBlock", blockHandlerClass = RestTemplateBlockHandler.class, fallback = "handleFallback", fallbackClass = RestTemplateFallback.class ) public RestTemplate restTemplate() { return new RestTemplate(); } } Feign集成 添加依赖 <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> 配置 feign: sentinel: enabled: true 使用 @FeignClient(name = "product-service", fallback = ProductServiceFallback.class) public interface ProductService { @GetMapping("/product/{id}") Product getProduct(@PathVariable Long id); } @Component public class ProductServiceFallback implements ProductService { @Override public Product getProduct(Long id) { return Product.builder() .id(id) .name("商品服务暂时不可用") .build(); } } 全局异常处理 @RestControllerAdvice public class SentinelExceptionHandler { @ExceptionHandler(FlowException.class) public Result handleFlowException(FlowException e) { return Result.error(429, "请求过于频繁"); } @ExceptionHandler(DegradeException.class) public Result handleDegradeException(DegradeException e) { return Result.error(503, "服务降级"); } @ExceptionHandler(BlockException.class) public Result handleBlockException(BlockException e) { return Result.error(500, "系统保护"); } } 规则初始化 @Configuration public class SentinelRuleConfig { @PostConstruct public void initRules() { initFlowRules(); initDegradeRules(); initSystemRules(); } private void initFlowRules() { List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(); rule.setResource("createOrder"); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setCount(100); rules.add(rule); FlowRuleManager.loadRules(rules); } private void initDegradeRules() { List<DegradeRule> rules = new ArrayList<>(); DegradeRule rule = new DegradeRule(); rule.setResource("callProductService"); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); rule.setCount(1000); rule.setSlowRatioThreshold(0.5); rules.add(rule); DegradeRuleManager.loadRules(rules); } private void initSystemRules() { List<SystemRule> rules = new ArrayList<>(); SystemRule rule = new SystemRule(); rule.setHighestCpuUsage(0.8); rules.add(rule); SystemRuleManager.loadRules(rules); } } 完整实战案例 @SpringBootApplication @EnableFeignClients public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } @RestController @RequestMapping("/order") public class OrderController { @Autowired private OrderService orderService; @PostMapping("/create") @SentinelResource(value = "orderCreate", blockHandler = "handleBlock") public Result createOrder(@RequestBody OrderDTO dto) { Order order = orderService.createOrder(dto); return Result.success(order); } public Result handleBlock(OrderDTO dto, BlockException ex) { return Result.error(429, "订单创建繁忙,请稍后重试"); } } @Service public class OrderService { @Autowired private ProductService productService; @SentinelResource(value = "createOrderService", fallback = "handleFallback") public Order createOrder(OrderDTO dto) { // 调用商品服务 Product product = productService.getProduct(dto.getProductId()); // 创建订单 Order order = new Order(); order.setProductId(product.getId()); order.setUserId(dto.getUserId()); return orderDao.save(order); } public Order handleFallback(OrderDTO dto, Throwable ex) { log.error("订单创建失败", ex); throw new BusinessException("订单创建失败,请重试"); } } 总结 Spring Boot集成Sentinel的关键点: ...

2025-11-20 · maneng

动态规则配置:从硬编码到配置中心

引言:硬编码规则的痛点 在前面的文章中,我们一直使用硬编码的方式配置Sentinel规则: @PostConstruct public void initFlowRule() { List<FlowRule> rules = new ArrayList<>(); FlowRule rule = new FlowRule(); rule.setResource("orderCreate"); rule.setCount(1000); // ← 硬编码在代码中 rules.add(rule); FlowRuleManager.loadRules(rules); } 硬编码规则的问题: 无法动态调整:修改限流阈值需要重新部署 无法统一管理:每个服务都要单独配置 无法应对突发情况:流量激增时无法快速调整 配置不可追溯:不知道谁在什么时候改了配置 解决方案:将规则配置到配置中心(如Nacos、Apollo),实现动态更新。 规则持久化的三种模式 1. 原始模式(内存模式) 特点: 规则存储在内存中 应用重启后规则丢失 Dashboard推送规则,应用无法持久化 问题:无法持久化,生产环境不推荐。 2. Pull模式(定时拉取) 工作流程: 应用启动 ↓ 定时从配置中心拉取规则(如每30秒) ↓ 更新内存中的规则 ↓ 继续定时拉取 优点:实现简单 缺点:实时性差,可能延迟30秒 3. Push模式(推送模式) 工作流程: Dashboard修改规则 ↓ 推送到配置中心(如Nacos) ↓ 配置中心通知所有订阅的应用 ↓ 应用实时更新规则 优点:实时性高(秒级) 缺点:实现复杂 推荐:生产环境使用Push模式 + Nacos。 Nacos配置中心集成(Push模式) 第一步:添加依赖 <!-- Sentinel Nacos数据源 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.6</version> </dependency> <!-- Nacos客户端 --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>2.2.0</version> </dependency> 第二步:配置application.yml spring: application: name: order-service cloud: sentinel: transport: dashboard: localhost:8080 datasource: # 流控规则 flow: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-flow-rules groupId: SENTINEL_GROUP rule-type: flow data-type: json # 熔断规则 degrade: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-degrade-rules groupId: SENTINEL_GROUP rule-type: degrade data-type: json # 系统保护规则 system: nacos: server-addr: localhost:8848 dataId: ${spring.application.name}-system-rules groupId: SENTINEL_GROUP rule-type: system data-type: json 第三步:在Nacos中配置规则 登录Nacos控制台(http://localhost:8848/nacos): ...

2025-11-20 · maneng

网关流控:统一流量入口的防护

引言:为什么要在网关层做流控? 在微服务架构中,API网关是所有外部流量的统一入口: 用户请求 ↓ 【API Gateway】 ← 在这里做流控 ↓ ┌───────┴───────┐ ↓ ↓ 订单服务 商品服务 为什么要在网关层做流控? 统一防护:一处配置,保护所有后端服务 提前拦截:在流量进入内网之前就拦截,节省资源 全局视角:可以基于租户、API、IP等多维度限流 安全防护:防止DDoS攻击、CC攻击 今天我们就来学习Sentinel在Spring Cloud Gateway中的集成和使用。 Spring Cloud Gateway + Sentinel集成 第一步:添加依赖 <!-- Spring Cloud Gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Sentinel Gateway适配器 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.8.6</version> </dependency> 第二步:配置Gateway application.yml: spring: application: name: api-gateway cloud: gateway: routes: # 订单服务路由 - id: order-service uri: lb://order-service predicates: - Path=/api/order/** filters: - StripPrefix=2 # 商品服务路由 - id: product-service uri: lb://product-service predicates: - Path=/api/product/** filters: - StripPrefix=2 第三步:配置Sentinel网关限流 import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem; import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver; import javax.annotation.PostConstruct; import java.util.*; @Configuration public class GatewaySentinelConfig { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewaySentinelConfig(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } /** * 配置Sentinel网关限流过滤器 */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } /** * 配置Sentinel网关限流异常处理器 */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } /** * 初始化网关限流规则 */ @PostConstruct public void initGatewayRules() { Set<GatewayFlowRule> rules = new HashSet<>(); // 规则1:订单服务限流 QPS 1000 rules.add(new GatewayFlowRule("order-service") .setCount(1000) .setIntervalSec(1)); // 规则2:商品服务限流 QPS 2000 rules.add(new GatewayFlowRule("product-service") .setCount(2000) .setIntervalSec(1)); GatewayRuleManager.loadRules(rules); System.out.println("✅ 网关限流规则已加载"); } } 网关限流的三种粒度 1. Route维度限流 含义:对整个路由进行限流。 ...

2025-11-20 · maneng

集群流控:跨实例的流量管理

引言:当单机限流不够用时 假设你的订单服务部署了3个实例,每个实例配置了QPS限流1000: 实例1:QPS限流 1000 实例2:QPS限流 1000 实例3:QPS限流 1000 问题来了:整个订单服务的总QPS是多少? 答案:3000 QPS(每个实例1000)。 但如果你的需求是"整个订单服务的总QPS不超过2000"呢? 传统的单机限流无法实现!因为每个实例各自统计,无法感知其他实例的流量。 这就是集群流控(Cluster Flow Control)要解决的问题。 单机限流的局限性 问题1:无法精确控制总流量 场景:3个实例,期望总QPS 2000。 单机限流配置: FlowRule rule = new FlowRule(); rule.setResource("orderCreate"); rule.setCount(667); // 2000 / 3 ≈ 667 问题: 流量不均匀时,会导致总QPS超限 某个实例挂了,总QPS会降低 示例: 场景 实例1 QPS 实例2 QPS 实例3 QPS 总QPS 结果 流量均匀 666 666 666 1998 ✅ 正常 流量不均 667 667 1000 2334 ❌ 超限 实例3挂 667 667 0 1334 ⚠️ 浪费 问题2:无法应对突发流量 场景:3个实例,某一秒流量全部打到实例1。 时刻 实例1 实例2 实例3 总QPS 期望 T0 667 ❌ 0 0 667 2000 T1 667 ❌ 0 0 667 2000 实例1已经限流了,但实例2和实例3还有大量闲置容量。 ...

2025-11-20 · maneng

黑白名单与授权规则

引言:不是所有请求都应该被处理 在前面的文章中,我们学习了限流、熔断、系统保护、热点限流,它们都是流量控制的手段——控制流量的数量和速度。 但在实际生产中,还有另一种需求:访问控制。 场景1:恶意爬虫 你的电商网站被某个爬虫疯狂抓取,虽然做了限流,但爬虫会换IP继续攻击。 需求:将这个爬虫的IP拉黑,直接拒绝访问。 场景2:内部接口 你有一个管理后台接口,只允许内网IP访问,外网IP不允许访问。 需求:设置IP白名单,只允许特定IP访问。 场景3:VIP用户 你的系统有普通用户和VIP用户,在流量高峰期,需要优先保证VIP用户的访问。 需求:VIP用户不限流,普通用户限流。 这些场景都需要授权规则(Authority Rule)——根据调用来源决定是否允许访问。 授权规则的核心概念 什么是授权规则? 授权规则是Sentinel提供的访问控制机制,可以根据**调用来源(origin)**决定是否允许请求通过。 核心要素: 调用来源(origin):标识请求来自哪里(如IP、用户ID、应用名) 策略(strategy):黑名单或白名单 限制应用(limitApp):具体的来源值列表 黑名单 vs 白名单 类型 策略 规则 适用场景 白名单 AUTHORITY_WHITE 只允许名单内的来源访问 内部接口、VIP服务 黑名单 AUTHORITY_BLACK 拒绝名单内的来源访问 封禁恶意用户、爬虫 工作流程 请求到达 ↓ 提取调用来源(origin) ↓ 查找授权规则 ↓ 判断是否在黑/白名单中 ↓ ├─ 白名单:在名单内 → 通过,不在 → 拒绝 └─ 黑名单:在名单内 → 拒绝,不在 → 通过 ↓ 返回结果 配置授权规则 基础配置:黑名单 import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import java.util.ArrayList; import java.util.List; public class AuthorityRuleConfig { public static void initBlackListRule() { List<AuthorityRule> rules = new ArrayList<>(); AuthorityRule rule = new AuthorityRule(); rule.setResource("userInfo"); // 资源名 rule.setStrategy(RuleConstant.AUTHORITY_BLACK); // 黑名单策略 rule.setLimitApp("app1,app2"); // 黑名单列表(逗号分隔) rules.add(rule); AuthorityRuleManager.loadRules(rules); System.out.println("✅ 黑名单规则已加载:拒绝 app1, app2 访问"); } } 配置说明: ...

2025-11-20 · maneng

热点参数限流:保护你的热点数据

引言:当80%的流量集中在20%的数据上 你是否遇到过这样的场景? 场景1:秒杀系统 双11,iPhone 15 Pro Max限量秒杀,1000台库存。 虽然你的商品详情接口做了限流(QPS 10000),但这1万个请求全部集中在这一个商品ID上! 其他普通商品无人问津,但这一个热点商品把数据库、缓存、库存服务全部打爆了。 场景2:直播平台 某顶流明星开始直播,500万人涌入直播间。 虽然你的直播接口做了限流(QPS 100000),但这10万个请求全部集中在这一个直播间ID上! 其他直播间正常,但这一个热点直播间导致整个直播服务崩溃。 这就是热点数据问题:少数数据承载了绝大部分流量,普通的限流无法精准保护。 这就需要Sentinel的热点参数限流(Hot Param Flow Control)。 什么是热点数据? 热点数据的定义 热点数据是指在一段时间内,访问频率远高于其他数据的数据。 典型案例: 场景 热点数据 流量分布 电商秒杀 iPhone 15 秒杀商品ID 80%流量集中在1个商品 视频平台 热门视频ID 90%播放量集中在TOP 100视频 社交平台 热门话题ID 70%讨论集中在热门话题 新闻网站 突发新闻ID 突发事件发生时,流量暴涨 直播平台 顶流主播直播间ID 500万人涌入1个直播间 热点数据的特点 不可预测:不知道哪个数据会成为热点 时间敏感:热点会随时间变化(如突发新闻) 流量集中:少数数据占据大部分流量 影响范围大:一个热点可能拖垮整个系统 普通限流的局限性 问题1:无法区分参数 案例:商品详情接口 @GetMapping("/product/{id}") public Product getProductDetail(@PathVariable Long id) { return productService.getById(id); } 限流配置: FlowRule rule = new FlowRule(); rule.setResource("getProductDetail"); rule.setCount(10000); // QPS 10000 问题: ...

2025-11-20 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...