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.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Mastering Dynamic Rate Limiting in Spring Cloud Gateway with Sentinel

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=1

RequestRateLimiterGatewayFilterFactory

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: true

Configure 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Nacossentinelrate limitingSpring Cloud Gateway
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.