Backend Development 10 min read

Rate Limiting in Spring Boot: Counter, Leaky & Token Buckets using Guava & Baidu

This article explains three classic rate‑limiting algorithms—counter, leaky bucket, and token bucket—illustrates their principles, compares their behavior, and provides practical Spring Boot implementations using Google Guava’s RateLimiter and Baidu’s ratelimiter‑spring‑boot‑starter, including configuration, code samples, and performance testing.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Rate Limiting in Spring Boot: Counter, Leaky & Token Buckets using Guava & Baidu

Environment: springboot2.3.9 + Guava30.1.1-jre

Rate Limiting Algorithms

Generally there are two rate‑limiting algorithms—leaky bucket and token bucket—plus a simple counter method.

Counter

Using a counter for rate limiting is straightforward: set a QPS limit (e.g., 100 requests per second). When the first request arrives, start a 1‑second window; each subsequent request increments an AtomicLong counter. If the counter reaches the threshold, further requests are rejected until the window expires and the counter resets to zero. This approach can cause a "burst" problem where early requests consume the quota and later requests are all blocked.

Leaky Bucket

The leaky bucket algorithm controls the rate at which data leaves a bucket, smoothing bursty traffic. It can be visualized as a bucket that receives incoming requests (water) and releases them at a constant rate; excess water overflows and is dropped, effectively rejecting excess requests.

The leaky bucket reliably controls access speed; requests exceeding the configured rate are denied.

Token Bucket

The token bucket algorithm adds tokens to a bucket at a constant rate. A request can proceed only if it successfully takes a token; otherwise it is rejected. Conceptually, it is the opposite of the leaky bucket: tokens are added ("water in") and requests consume them ("water out").

After understanding the three algorithms, we explore how to apply them in a project.

Use Google Guava library RateLimiter

Guava's RateLimiter implements a token‑bucket algorithm. It issues tokens at a fixed rate; a thread must acquire a token before proceeding. RateLimiter does not support clustered environments, which require external stores like Redis.

Dependency:

<code>&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
    &lt;artifactId&gt;guava&lt;/artifactId&gt;
    &lt;version&gt;30.1.1-jre&lt;/version&gt;
&lt;/dependency&gt;</code>

Goal: allow only 3 requests per second.

<code>@RestController
@RequestMapping("/products")
public class ProductController {
    private final RateLimiter rateLimiter = RateLimiter.create(5.0);

    @GetMapping("/{id}")
    public ResponseEntity<R> queryProducts(@PathVariable("id") String id) throws Exception {
        if (rateLimiter.tryAcquire(1)) {
            TimeUnit.MILLISECONDS.sleep(200);
            return new ResponseEntity<>(R.success("查询商品【" + id + "】成功"), HttpStatus.OK);
        }
        return new ResponseEntity<>(R.failure("你访问的太快了"), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}</code>

Testing with JMeter 5.4.1 (100 concurrent threads, 2 loops) shows the rate limit in action.

Interface configuration screenshot:

Test results screenshot:

RateLimiter related methods illustration:

Use Baidu's ratelimiter‑spring‑boot‑starter

ratelimiter‑spring‑boot‑starter provides single‑node rate limiting for Spring Boot services; it can be integrated into Spring Cloud projects as well.

Limiting dimensions : node‑level, method‑level, service‑level.

Node‑level: each service instance applies its own rules.

Method‑level: each HTTP method+URI can have separate rules.

Service‑level: a global rule for all requests to the instance; both service‑level and method‑level are evaluated, and any rejection blocks the request.

Dependency:

<code>&lt;dependency&gt;
    &lt;groupId&gt;com.baidubce.formula&lt;/groupId&gt;
    &lt;artifactId&gt;ratelimiter-spring-boot-starter&lt;/artifactId&gt;
    &lt;version&gt;2.1.1.1&lt;/version&gt;
&lt;/dependency&gt;</code>

Application configuration:

<code>spring:
  application:
    name: ratelimiter
---
formula:
  ratelimiter:
    enabled: true
    ratelimiters:
      - effectiveLocation: /products/q/**
        effectiveType: 1
        enabled: true
        httpMethod: GET
        limiterType: 1
        threshold: 5</code>

Note:

spring.application.name

must be set; the

source

field is undocumented.

API example:

<code>@GetMapping("/q/{id}")
public ResponseEntity<R> queryProduct(@PathVariable("id") String id) throws Exception {
    TimeUnit.MILLISECONDS.sleep(200);
    return new ResponseEntity<>(R.success("查询商品【" + id + "】成功"), HttpStatus.OK);
}</code>

Failed requests return HTTP 429 Too Many Requests.

Core filter class in Baidu’s tool (RateLimiterEffectiveFilter.java) is shown below.

Key methods such as

waitForPermit

and

waitForPermission

are illustrated.

HttpUtil#isBlockException can be overridden to customize the block response.

<code>public static boolean isBlockException(HttpServletResponse response, Exception e) throws IOException {
    if (e instanceof BlockException) {
        response.setStatus(429);
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().print("{\"code\": -1, \"message\": \"你的请求太快了\"}");
        response.flushBuffer();
        return true;
    } else {
        return false;
    }
}</code>

After modifying and testing, the custom behavior works as expected.

BackendJavaSpring BootGuavaRate Limitingtoken bucketleaky bucket
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

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