Mastering Dynamic Rate Limiting in Spring Cloud Gateway with Sentinel
This article examines the limitations of Spring Cloud Gateway's native RequestRateLimiter, introduces Sentinel's flow control integration, provides Maven dependencies, configuration examples, and demonstrates dynamic rate‑limiting adjustments via Nacos, illustrating effective traffic protection for microservice gateways.
Limitations of Native RequestRateLimiter
Configuration method
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: lb://pigx-upms
order: 10000
predicates:
- Path=/admin/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 3
key-resolver: "#{@remoteAddrKeyResolver}"
- StripPrefix=1RequestRateLimiterGatewayFilterFactory
public GatewayFilter apply(Config config) {
KeyResolver resolver = getOrDefault(config.keyResolver, defaultKeyResolver);
RateLimiter<Object> limiter = getOrDefault(config.rateLimiter, defaultRateLimiter);
boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
HttpStatusHolder emptyKeyStatus = HttpStatusHolder
.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));
return (exchange, chain) -> {
return exchange.getResponse().setComplete();
};
}In production, static configuration cannot meet dynamic needs; RequestRateLimiterGatewayFilterFactory cannot adjust limits in real time based on traffic.
Sentinel Flow Control
With the rise of microservices, stability between services is crucial. Sentinel provides traffic control, circuit breaking, system load protection, and from version 1.6.0 offers Spring Cloud Gateway integration with route‑level and custom API‑level rate limiting.
pom dependencies
<!--Spring Cloud Alibaba sentinel module-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--Use Nacos to store rate‑limit rules-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>Local route configuration and Sentinel datasource
spring:
application:
name: sentinel-spring-cloud-gateway
cloud:
gateway:
enabled: true
discovery:
locator:
lower-case-service-id: true
routes:
- id: pigx_route
uri: https://api.readhub.cn
predicates:
- Path=/topic/**
sentinel:
datasource.ds1.nacos:
server-addr: 127.0.0.1:8848
data-id: gw-flow
group-id: DEFAULT_GROUP
ruleType: gw-api-group
filter:
enabled: trueConfigure Nacos datasource rate‑limit strategies
Common limit‑strategy constants:
public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
public static final int PARAM_PARSE_STRATEGY_HOST = 1;
public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;Core source analysis – SentinelGatewayFilter
Sentinel extends the Gateway filter, using different GatewayParamParser implementations to compare request factors with datasource configurations.
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
Mono<Void> asyncResult = chain.filter(exchange);
if (route != null) {
String routeId = route.getId();
Object[] params = paramParser.parseParameterFor(routeId, exchange,
r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
String origin = Optional.ofNullable(GatewayCallbackManager.getRequestOriginParser())
.map(f -> f.apply(exchange))
.orElse("");
asyncResult = asyncResult.transform(
new SentinelReactorTransformer<>(new EntryConfig(routeId, EntryType.IN,
1, params, new ContextConfig(contextName(routeId), origin)))
);
}
Set<String> matchingApis = pickMatchingApiDefinitions(exchange);
for (String apiName : matchingApis) {
Object[] params = paramParser.parseParameterFor(apiName, exchange,
r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME);
asyncResult = asyncResult.transform(
new SentinelReactorTransformer<>(new EntryConfig(apiName, EntryType.IN, 1, params))
);
}
return asyncResult;
}Demo
Configured Nacos to allow 5 requests per second; tested with JMeter 4.0 using 10 concurrent threads.
The results confirm Sentinel's rate limiting works effectively.
Dynamic modification of limit parameters
The sentinel-datasource-nacos datasource enables real‑time refresh of limit parameters from the Nacos console.
Sentinel Dashboard 1.6.2 does not yet provide graphical gateway flow control; version 1.7.0 will add this feature.
Conclusion
The code is based on a personal project using Spring Cloud, OAuth2.0, and a Vue front‑back separation platform.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
