Comprehensive Guide to Implementing Rate Limiting in Java Microservices Using Guava, Sentinel, Redis, and a Custom Spring Boot Starter

This article explains why rate limiting is critical for microservice architectures, reviews common limiting algorithms, and provides step‑by‑step implementations using Dubbo, Spring Cloud, Guava token‑bucket, Sentinel, Redis+Lua, and a reusable Spring Boot starter with custom annotations and AOP.

Architecture Digest
Architecture Digest
Architecture Digest
Comprehensive Guide to Implementing Rate Limiting in Java Microservices Using Guava, Sentinel, Redis, and a Custom Spring Boot Starter

Background – In a microservice system, uncontrolled traffic can cause a hidden avalanche effect; limiting request rates protects downstream services from overload.

Rate‑limiting overview – Different governance frameworks (Dubbo, Spring Cloud) require different limiting strategies, including client‑side and server‑side controls.

Common limiting algorithms

Token bucket – tokens are generated at a fixed rate and consumed by requests.

Leaky bucket – requests fill a bucket; excess traffic is dropped.

Sliding window – counts requests within a moving time window.

Implementation examples

1. Guava token‑bucket

Add the Guava dependency:

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>23.0</version>
</dependency>

Create a custom annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenBucketLimiter {
    int value() default 50;
}

Implement the AOP logic:

@Aspect
@Component
public class GuavaLimiterAop {
    private final Map<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();
    @Pointcut("@annotation(com.congge.annotation.TokenBucketLimiter)")
    public void point() {}
    @Around("point()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Method method = // resolve method
        TokenBucketLimiter limiter = method.getAnnotation(TokenBucketLimiter.class);
        RateLimiter rl = rateLimiters.computeIfAbsent(methodKey, k -> RateLimiter.create(limiter.value()));
        if (rl.tryAcquire()) {
            return point.proceed();
        } else {
            // return rate‑limit response
            HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            JSONObject json = new JSONObject();
            json.put("success", false);
            json.put("msg", "限流中");
            output(resp, json.toJSONString());
            return null;
        }
    }
    private void output(HttpServletResponse response, String msg) throws IOException { /* ... */ }
}

2. Sentinel limit

Add Sentinel core dependency:

<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-core</artifactId>
  <version>1.8.0</version>
</dependency>

Custom annotation and AOP are similar to the Guava example, using SphU.entry(resourceName) and handling BlockException to return a “blocked” message.

3. Redis + Lua limit

Add Spring Data Redis dependency and a Lua script (limit.lua) that increments a key and expires it after a short period.

local key = "rate.limit:" .. KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then
  return 0
else
  redis.call('INCRBY', key, '1')
  redis.call('expire', key, '2')
  return current + 1
end

The AOP reads the annotation, builds a unique key (IP + class + method), executes the script via redisTemplate.execute(redisluaScript, keys, limit, period), and proceeds only when the returned count is within the limit.

4. Custom Spring Boot starter

Package the above annotations and AOP classes into a separate module, expose them via spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.congge.aop.SemaphoreLimiterAop,\
  com.congge.aop.GuavaLimiterAop,\
  com.congge.aop.SentinelLimiterAop

Publish the jar and import it in other services; the rate‑limiting behavior works out‑of‑the‑box.

Overall, the article walks through the theory, algorithm choices, and concrete code for three popular limiting mechanisms and shows how to encapsulate them into a reusable starter for production microservice projects.

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.

JavaaopredisSpring BootsentinelGuavarate limiting
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

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.