Spring Cloud 微服务 Sentinel 热点参数与授权规则集成指南(附架构建议)

Spring Cloud 微服务 Sentinel 热点参数与授权规则集成指南(附架构建议)

🌟 核心结论与架构建议(必读)

在开始集成前,必须明确:Sentinel 的规则配置应遵循"职责分离,按需引入"原则,拒绝过度设计。

  • order-service(普通业务微服务) :不需要 集成"热点规则"和"授权规则"。应保持业务代码绝对干净,仅使用控制台直接生效的流控规则、熔断规则、系统规则。
  • api-gateway(网关层):必须接管所有安全与全局拦截逻辑。所有外网流量的鉴权、黑白名单、防刷,只能在网关层完成。
  • 什么时候才用热点和授权?
    • 热点规则:仅当有明确痛点(如秒杀、刷单等"同一个参数被高频请求"的场景)时才引入,且需改业务代码。
    • 授权规则 :属于业务微服务的架构反模式(污染代码、极易误杀),强烈建议只在网关做。

1. 背景与前提

  • 版本环境 :Sentinel 1.8.x,Spring Cloud Gateway(api-gateway),普通 Spring Boot 微服务(order-service)。
  • 核心痛点 :Sentinel 默认的 Web 拦截器只能识别 URL,拿不到方法参数 ,也不知道请求来源。因此,热点规则和授权规则无法仅靠控制台配置生效,必须进行代码改造。

2. 热点规则集成(Hotspot Rule)

目标 :对接口的某个具体参数(如 userId、ip)进行独立限流,防止特定参数被恶意刷爆。

2.1 order-service 代码修改

第一步:引入依赖(若未引入)

确保 pom.xml 中包含 Sentinel 核心依赖:

xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

第二步:在 Controller 方法上添加 @SentinelResource 注解

必须使用该注解,Sentinel 才能通过 AOP 切面获取到方法参数。

java 复制代码
@RestController
@RequestMapping("/api/order")
public class OrderController {

    // value 必须与控制台配置的资源名一致
    // blockHandler 指定限流后的兜底方法
    @GetMapping("/detail")
    @SentinelResource(value = "/order-service/api/order/detail", blockHandler = "handleHotspotBlock")
    public Result detail(String userId, String ip) {
        // 正常业务逻辑
        return Result.success(...);
    }

    // 兜底方法要求:
    // 1. 访问修饰符必须是 public
    // 2. 返回值类型、参数类型和顺序必须与原方法一致
    // 3. 必须在参数列表最后额外加上 BlockException 参数
    public Result handleHotspotBlock(String userId, String ip, BlockException ex) {
        // 返回统一的限流响应,例如 HTTP 429
        return Result.error("请求过于频繁,请稍后再试");
    }
}

⚠️ 注意:热点参数必须是基本类型或 String。如果是自定义对象,Sentinel 无法直接解析内部字段,需提前将其拆解为独立参数。

2.2 api-gateway 代码修改

无需任何代码修改。网关只需正常转发请求(确保 URL 和参数透传即可)。

2.3 控制台配置指南

  1. 资源名 :填写注解中的 value,如 /order-service/api/order/detail。
  2. 参数索引 :从 0 开始。假设 detail(String userId, String ip),限制 userId 就填 0,限制 ip 就填 1。
  3. 单机阈值 :填正整数(如 10)。
  4. 统计窗口时长 :通常为 1 秒。
  5. 高级选项(参数例外项):可对特定参数值(如 VIP 用户 ID)单独设置更高的阈值。

3. 授权规则集成(Authority Rule)

目标 :实现基于调用来源的黑白名单。只允许 api-gateway 调用,拒绝其他所有非法来源(如直接绕过网关的 Postman 请求)。

3.1 order-service 代码修改

核心:实现 RequestOriginParser 接口

Sentinel 需要知道从哪里提取"来源标识"。我们需要从 HTTP Header 中提取。

java 复制代码
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;

@Component
public class CustomRequestOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 从网关透传的 Header 中获取来源
        String origin = request.getHeader("X-Sentinel-Origin");
        // ⚠️ 极其重要:如果获取不到,必须返回空字符串,绝不能返回 null
        // Sentinel 源码规定:Origin 为空字符串时会默认放行(Pass),而不是拦截
        return StringUtils.isBlank(origin) ? "" : origin;
    }
}

注:如果不写这段代码,Sentinel 默认返回空串,所有授权规则会因为"来源为空"而默认放行,导致规则形同虚设。

3.2 api-gateway 代码修改

核心:编写全局过滤器(GlobalFilter),注入来源 Header

网关在将请求转发给 order-service 之前,必须打上标记。

java 复制代码
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import reactor.core.publisher.Mono;

@Component
public class SentinelOriginFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 向请求头中追加来源标识
        ServerWebExchange mutatedExchange = exchange.mutate()
                .request(builder -> builder.header("X-Sentinel-Origin", "api-gateway"))
                .build();
        return chain.filter(mutatedExchange);
    }

    @Override
    public int getOrder() {
        // 确保在路由转发前执行
        return -100;
    }
}

3.3 控制台配置指南

  1. 资源名 :填写受保护的 URL,如 /order-service/api/order/detail。
  2. 流控应用 :填写允许调用的应用名,如 api-gateway(多个用逗号分隔)。
  3. 授权类型 :选择 白名单。

联动效果:

  • 经过 api-gateway 转发的请求,Header 中有 X-Sentinel-Origin: api-gateway。Sentinel 提取到该值,匹配白名单,放行。
  • 使用 Postman 直接请求 order-service 的接口,Header 中无 X-Sentinel-Origin。Sentinel 提取到空值,默认放行(如果想拦截,需要在解析器里返回一个不匹配的值,例如 "unknown")。
  • 如果白名单拦截逻辑需严格,建议修改 parseOrigin 方法返回 "unknown",这样未经过网关的请求会被强制拦截。

4. 最佳实践与避坑总结

  1. 微服务规则选型推荐 :
    • 业务微服务必配:流控规则(保护自身)、熔断规则(防雪崩)、系统规则(实例保底防线)。这些均不需要改代码。
    • 网关层必配 :网关流控规则(gw-flow,全局防刷)、API 管理(分组限流)。安全鉴权和全局黑白名单必须在网关层实现。
  2. 热点规则的应用场景:适用于秒杀、刷单等高并发场景。如果接口没有明确的热点参数,直接用普通"流控规则"即可,避免引入不必要的代码复杂度。
  3. 授权规则的架构原则 :
    • 在网关层做统一鉴权和全局拦截是首选架构,能避免将安全逻辑分散到所有业务微服务中。
    • 如果在业务微服务做授权,务必确保 RequestOriginParser 的返回值逻辑严谨(空值放行是 Sentinel 默认行为,极易被绕过)。
  4. 兜底方法(BlockHandler)的规范 :blockHandler 方法必须与原方法在同一个类中,且参数列表、返回值必须完全对应,最后追加 BlockException 参数。
  5. 规则持久化:控制台配置的规则默认存在内存中,重启服务会丢失。生产环境必须接入 Nacos、Apollo 或 ZooKeeper 实现规则的持久化推送。
相关推荐
池佳齐3 小时前
【软考高级架构师案例】软件测试架构:不仅是黑盒白盒,自动化测试体系该怎么设计?
架构
沪上企服通3 小时前
规则引擎版本化:把代账科目映射当 policy-as-code 管(上海 5 家样本对照)
笔记·架构
Thneonl3 小时前
ZK、etcd、Consul 怎么选:差别不在共识,在壳
后端·架构
微订校园外卖平台3 小时前
校园跑腿小程序上线:四端架构与校园外卖系统履约链路拆解
小程序·架构·外卖系统·本地生活·微订
colorknight3 小时前
从事件到行动:HuggingFists 事件中心技术解析
架构·事件驱动·huggingfists·事件中心
eBest数字化转型方案4 小时前
下沉市场渠道系统建设:低密度终端网络的数字化架构实践
架构
深圳云识客4 小时前
8寸人脸识别门禁装到开源鸿蒙上:光学和安装高比屏尺寸先定
物联网·架构
用户3058759549314 小时前
单体、微服务、集群、高可用:把软件架构听明白
架构
Ikalus19884 小时前
四枚 JWT 全部验签通过,两个被算成了同一个人——错在 sub 少了 iss
安全·架构