Comprehensive Guide to Rate Limiting in Microservice Architecture Using Dubbo, Spring Cloud, Sentinel, Redis, and Custom Starters
This article explains the importance of rate limiting in microservice systems, compares various governance frameworks such as Dubbo and Spring Cloud, and provides detailed implementations using Guava, Sentinel, Redis+Lua scripts, and a custom Spring Boot starter, complete with code examples and deployment steps.
Background
Rate limiting is crucial in a micro‑service architecture because a single overloaded service can become a hidden avalanche factor, causing request blocking, queuing, and time‑outs that eventually exhaust JVM resources.
Rate‑Limiting Overview
When selecting a technology stack (e.g., Dubbo vs. Spring Cloud), the rate‑limiting solution must fit the overall architecture, business requirements, and team capabilities.
2.1 Dubbo Service Governance
Dubbo uses Netty under the hood, offering advantages over HTTP in certain scenarios. Dubbo provides both client‑side and server‑side limiting mechanisms.
Client‑side limits : semaphore limiting, connection‑count limiting (socket‑tcp).
Server‑side limits : thread‑pool isolation, semaphore limiting, receive‑count limiting.
2.1.1 Dubbo Framework‑Level Limiting
Dubbo’s official configuration supports these limits; refer to the official manual for exact XML snippets.
2.1.2 Thread‑Pool Configuration
Dubbo supports four thread‑pool types. The <dubbo:protocol> tag can configure core size, max size, and queue length to achieve basic throttling.
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>2.1.3 Integrating Third‑Party Components
For Spring Boot projects, you can directly add Hystrix, Guava, or Sentinel SDKs, or even implement a custom solution.
2.2 Spring Cloud Service Governance
Spring Cloud and Spring Cloud‑Alibaba already bundle common limiting components that work out‑of‑the‑box.
2.2.1 Hystrix
Hystrix provides thread‑isolation based limiting; you can configure thread count and queue size to control QPS.
2.2.2 Sentinel
Sentinel is a flow‑control component for distributed systems, offering limiting, circuit‑breaking, degradation, and hotspot protection.
2.3 Gateway‑Level Limiting
Placing limits at the API‑gateway protects the entire system from malicious traffic, crawlers, and attacks.
Common Limiting Strategies
3.1 Algorithms
Typical algorithms include token‑bucket, leaky‑bucket, and sliding‑window.
3.1.1 Token Bucket
The bucket stores tokens; a request proceeds only if it can acquire a token.
3.1.2 Leaky Bucket
Requests are placed in a bucket; when the bucket is full, new requests are dropped.
3.1.3 Sliding Window
A time window slides forward, counting requests in sub‑intervals to provide smoother throttling.
General Implementation Approaches
Using AOP combined with custom annotations allows you to apply rate limiting to specific methods or interfaces without scattering logic throughout the codebase.
4.1 Guava‑Based Limiting
Guava’s RateLimiter implements a token‑bucket algorithm.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateConfigAnno {
String limitType();
double limitCount() default 5d;
} @Aspect
@Component
public class GuavaLimitAop {
private static final Logger logger = LoggerFactory.getLogger(GuavaLimitAop.class);
@Before("execution(@RateConfigAnno * *(..))")
public void limit(JoinPoint joinPoint) {
Method method = getCurrentMethod(joinPoint);
if (method == null) return;
String limitType = method.getAnnotation(RateConfigAnno.class).limitType();
double limitCount = method.getAnnotation(RateConfigAnno.class).limitCount();
RateLimiter limiter = RateLimitHelper.getRateLimiter(limitType, limitCount);
if (limiter.tryAcquire()) {
System.out.println("获取到令牌");
} else {
// return JSON indicating throttling
}
}
// helper methods omitted for brevity
} public class RateLimitHelper {
private static final Map<String, RateLimiter> rateMap = new HashMap<>();
public static RateLimiter getRateLimiter(String limitType, double limitCount) {
return rateMap.computeIfAbsent(limitType, k -> RateLimiter.create(limitCount));
}
}4.2 Sentinel‑Based Limiting
Sentinel can be used either with Spring Cloud‑Alibaba or as a native SDK.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SentinelLimitAnnotation {
String resourceName();
int limitCount() default 5;
} @Aspect
@Component
public class SentinelMethodLimitAop {
@Around("@annotation(com.example.SentinelLimitAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getCurrentMethod(joinPoint);
String resource = method.getAnnotation(SentinelLimitAnnotation.class).resourceName();
int count = method.getAnnotation(SentinelLimitAnnotation.class).limitCount();
initFlowRule(resource, count);
try (Entry entry = SphU.entry(resource)) {
return joinPoint.proceed();
} catch (BlockException e) {
return "被限流了";
}
}
// initFlowRule and getCurrentMethod omitted for brevity
}4.3 Redis + Lua Limiting
Redis provides atomic operations and can execute a Lua script to enforce limits.
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 @Aspect
@Component
public class LimitRestAspect {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private DefaultRedisScript<Number> redisluaScript;
@Around("@annotation(com.example.RedisLimitAnnotation)")
public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
RedisLimitAnnotation anno = method.getAnnotation(RedisLimitAnnotation.class);
String key = buildKey(joinPoint, anno);
Number count = redisTemplate.execute(redisluaScript, Collections.singletonList(key), anno.count(), anno.period());
if (count != null && count.intValue() <= anno.count()) {
return joinPoint.proceed();
}
throw new RuntimeException("访问频率过快,被限流了");
}
// buildKey omitted for brevity
}Custom Starter Implementation
To avoid duplicating rate‑limiting logic across many micro‑services, the article shows how to package the AOP classes, annotations, and auto‑configuration into a Spring Boot starter.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.aop.SemaphoreLimiterAop,\
com.example.aop.GuavaLimiterAop,\
com.example.aop.SentinelLimiterAopAfter publishing the starter as a JAR, other services can simply add the dependency and annotate methods with @TokenBucketLimiter, @ShLimiter, or @SentinelLimiter to obtain out‑of‑the‑box throttling.
Conclusion
Rate limiting is an essential part of service governance; the article provides practical code samples for Dubbo, Spring Cloud, Sentinel, Redis, and a reusable starter, helping developers protect system stability and prevent cascading failures.
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.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
