在 Spring Cloud Gateway 与 Sentinel 结合的架构中,实现“单个商户限流”“VIP 商户限流”“全局限流”需通过 多级规则设计 和 参数识别 实现,核心是利用 Sentinel 的网关流控规则、热点参数规则和授权规则,结合支付场景的业务标识(如商户 ID、用户等级)进行精细化控制。以下是具体实现方案:
一、基础准备:环境与参数提取
1. 依赖与网关配置
确保已引入 Spring Cloud Gateway 和 Sentinel 相关依赖(参考前文),并在网关路由中匹配支付相关接口(如 /pay/**
)。
2. 提取商户标识与用户等级
支付场景中,需从请求中提取 商户 ID(merchantId) 和 用户等级(如 VIP 标识),作为限流的依据。通过自定义过滤器或 RequestOriginParser
实现:
import com.alibaba.csp.sentinel.adapter.gateway.sc.request.SentinelGatewayRequestContext;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
@Configuration
public class PayRequestContextConfig {
// 提取商户ID和用户等级,存入Sentinel上下文
@Bean
public GlobalFilter payContextFilter() {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 从请求头或参数中获取商户ID(实际场景需按业务定义)
String merchantId = request.getHeaders().getFirst("X-Merchant-Id");
// 从请求头获取用户等级(如"VIP"或"DEFAULT")
String userLevel = request.getHeaders().getFirst("X-User-Level");
// 将商户ID存入Sentinel上下文,用于后续规则匹配
if (merchantId != null) {
SentinelGatewayRequestContext ctx = SentinelGatewayRequestContext.getCurrentContext();
ctx.setOrigin(merchantId); // 用origin存储商户ID
// 额外存储用户等级到属性中
ctx.getAttributes().put("userLevel", userLevel);
}
return chain.filter(exchange);
};
}
}
二、三级限流实现方案
1. 全局限流:控制网关总流量
目标:限制网关每秒处理的总请求数,防止整体过载(如大促期间总流量超过系统承载能力)。
实现方式:通过 Sentinel 网关流控规则,对网关全局设置 QPS 阈值。
-
配置步骤:
在 Sentinel 控制台新增“网关流控规则”:- 资源名:
pay-gateway
(网关应用名,代表全局资源) - 阈值类型:QPS
- 阈值:10000(根据系统承载能力设置,如每秒最多10万请求)
- 限流模式:直接
- 匹配策略:全部(对所有路由和接口生效)
- 资源名:
-
效果:当网关总请求数超过 10000 QPS 时,超出部分被拦截,返回降级响应(如“系统繁忙,请稍后重试”)。
2. 单个商户限流:限制单商户请求频率
目标:防止单个商户(如高频交易的商户)的请求占用过多资源,影响其他商户(如避免恶意刷单、接口滥用)。
实现方式:基于 Sentinel 热点参数规则,以“商户 ID”为参数设置限流阈值。
-
配置步骤:
-
标记热点参数:通过前文的
payContextFilter
,已将merchantId
作为参数存入上下文,需在网关中关联资源与参数:// 在网关配置中,为支付接口标记热点参数 @Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes() .route("pay-service", r -> r.path("/pay/**") .filters(f -> f // 为接口标记资源名,并指定商户ID为热点参数(索引0) .filter((exchange, chain) -> { String resource = "pay-service:/pay/**"; // 资源名 String merchantId = exchange.getRequest().getHeaders().getFirst("X-Merchant-Id"); if (merchantId != null) { // 将商户ID作为热点参数传入Sentinel SentinelGatewayRequestContext.getCurrentContext().setHotParams(resource, merchantId); } return chain.filter(exchange); }) ) .uri("lb://pay-service")) .build(); }
-
配置热点规则:在 Sentinel 控制台新增“热点规则”:
- 资源名:
pay-service:/pay/**
(与上述标记的资源一致) - 参数索引:0(对应商户ID参数)
- 单机阈值:500(单个商户每秒最多500次请求)
- 参数类型:字符串(商户ID为字符串类型)
- 资源名:
-
-
效果:单个商户的请求超过 500 QPS 时,超出部分被拦截,不影响其他商户的正常请求。
3. VIP 商户限流:为VIP商户提升阈值
目标:对 VIP 商户(如付费商户、大客户)给予更高的流量配额,保障其服务质量。
实现方式:通过 Sentinel 热点规则的“参数例外项”,为 VIP 商户 ID 单独设置更高阈值。
-
配置步骤:
在“单个商户限流”的热点规则基础上,添加“参数例外项”:- 例外参数值:VIP商户的 ID(如 "merchant_1001"、"merchant_1002")
- 例外阈值:1000(VIP商户每秒最多1000次请求,是普通商户的2倍)
- 匹配策略:精确匹配
若 VIP 商户较多,可结合 授权规则 实现批量处理:
- 配置授权规则,将 VIP 商户 ID 加入白名单:
- 资源名:
pay-service:/pay/**
- 授权类型:白名单
- 授权值:
VIP_MERCHANT
(自定义标识)
- 资源名:
- 在
payContextFilter
中,对 VIP 商户设置 origin 为VIP_MERCHANT
,普通商户为默认值:// 改造payContextFilter,为VIP商户设置特殊origin if ("VIP".equals(userLevel)) { ctx.setOrigin("VIP_MERCHANT"); // VIP商户origin } else { ctx.setOrigin(merchantId); // 普通商户用merchantId }
- 为 VIP 商户单独配置流控规则(阈值更高),资源名为
pay-service:/pay/**
,限制来源为VIP_MERCHANT
。
-
效果:VIP 商户的请求阈值提升至 1000 QPS,普通商户仍为 500 QPS,实现差异化限流。
三、规则优先级与冲突处理
三种限流规则同时生效时,需明确优先级:
- 全局限流:优先级最低,仅当总流量超过全局阈值时触发(无论单个商户是否超限)。
- 单个商户限流:优先级中等,若单商户流量超限,即使全局流量未达上限,也会被拦截。
- VIP 商户限流:优先级最高,VIP 规则会覆盖普通商户规则(如同一商户既是 VIP 又是普通商户,以 VIP 阈值为准)。
示例:若全局阈值 10000 QPS,普通商户 A 阈值 500 QPS,VIP 商户 B 阈值 1000 QPS:
- 当 A 发送 600 QPS 时,被单商户规则拦截 100 QPS(全局流量未超,不触发全局限流)。
- 当 B 发送 1200 QPS 时,被 VIP 规则拦截 200 QPS。
- 当所有商户总流量达 11000 QPS 时,全局限流拦截 1000 QPS(优先拦截非核心商户)。
四、规则持久化与动态更新
为避免网关重启后规则丢失,需将规则持久化到 Nacos 配置中心:
- 配置 Nacos 数据源(
application.yml
):
spring:
cloud:
sentinel:
datasource:
# 全局限流规则
gw-global:
nacos:
server-addr: localhost:8848
data-id: pay-gateway-global-rules
group-id: SENTINEL_GROUP
rule-type: gw-flow
# 单个商户热点规则
hot-merchant:
nacos:
server-addr: localhost:8848
data-id: pay-gateway-hot-rules
group-id: SENTINEL_GROUP
rule-type: param_flow
# VIP商户授权规则
auth-vip:
nacos:
server-addr: localhost:8848
data-id: pay-gateway-auth-rules
group-id: SENTINEL_GROUP
rule-type: authority
- Nacos 规则配置示例(以热点规则为例,
pay-gateway-hot-rules
):
[
{
"resource": "pay-service:/pay/**",
"count": 500,
"grade": 1,
"paramIdx": 0,
"paramFlowItemList": [
{
"object": "merchant_1001", // VIP商户ID
"count": 1000, // VIP阈值
"classType": "java.lang.String"
},
{
"object": "merchant_1002", // 另一VIP商户
"count": 1000,
"classType": "java.lang.String"
}
]
}
]
五、监控与验证
-
监控指标:通过 Sentinel 控制台或 Prometheus 监控:
- 全局限流次数:
sentinel_gateway_requests_blocked{resource="pay-gateway"}
- 单商户限流次数:
sentinel_param_flow_block{resource="pay-service:/pay/**"}
- VIP 商户通过次数:
sentinel_requests_passed{origin="VIP_MERCHANT"}
- 全局限流次数:
-
验证方式:
- 用 JMeter 模拟多商户并发请求,观察普通商户和 VIP 商户的限流效果。
- 模拟总流量超过全局阈值,验证全局限流是否生效。
总结
通过 Spring Cloud Gateway 与 Sentinel 的结合,可实现“全局-商户-等级”三级限流:
- 全局限流 保障系统整体稳定,防止总流量过载;
- 单个商户限流 避免资源被单一商户独占;
- VIP 商户限流 通过参数例外项或授权规则实现差异化服务。
核心是利用 Sentinel 的规则引擎和参数识别能力,结合支付场景的业务标识(商户 ID、用户等级),实现“既控总量,又分优先级”的精细化流量治理,最终保障支付链路的稳定性和公平性。