在系统中如何集成限流组件单机和集群
RateLimiter 详解及示例
1. 什么是 RateLimiter?
RateLimiter
是一种用于控制资源访问速率的工具,通常用于限制系统在单位时间内处理的请求数量。它基于令牌桶算法实现,通过动态生成令牌来控制请求的执行频率。
2. RateLimiter 的工作原理
RateLimiter
使用令牌桶算法来实现限流。系统以固定的速率向桶中添加令牌,每个请求需要消耗一个令牌。如果桶中没有足够的令牌,请求将被限流。
3. RateLimiter 的核心方法
-
RateLimiter.create(double permitsPerSecond)
:创建一个平滑突发限制的限流器,permitsPerSecond
表示每秒允许的请求数。 -
RateLimiter.acquire()
:阻塞当前线程,直到获取到令牌。 -
RateLimiter.tryAcquire()
:尝试获取令牌,如果令牌不足,立即返回false
,不会阻塞线程。
4. RateLimiter 示例代码
示例 1:平滑突发限制
java复制
import com.google.common.util.concurrent.RateLimiter;
public class RateLimiterExample {
public static void main(String[] args) {
// 创建一个每秒允许 2 个请求的限流器
RateLimiter rateLimiter = RateLimiter.create(2.0);
for (int i = 1; i <= 10; i++) {
// 尝试获取令牌
if (rateLimiter.tryAcquire()) {
System.out.println("处理请求: " + i);
} else {
System.out.println("请求被限流: " + i);
}
}
}
}
这个示例中,RateLimiter
每秒最多允许 2 个请求通过。
示例 2:平滑预热限制
java复制
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.TimeUnit;
public class SmoothWarmingUpExample {
public static void main(String[] args) {
// 每秒允许 2 个请求,预热时间为 3 秒
RateLimiter rateLimiter = RateLimiter.create(2.0, 3, TimeUnit.SECONDS);
for (int i = 1; i <= 10; i++) {
double waitTime = rateLimiter.acquire();
System.out.println("处理请求: " + i + ", 等待时间: " + waitTime + " 秒");
}
}
}
这个示例中,RateLimiter
在预热阶段会逐渐增加令牌的生成速率,最终达到每秒 2 个请求。
示例 3:非阻塞式限流
java复制
import com.google.common.util.concurrent.RateLimiter;
public class NonBlockingExample {
public static void main(String[] args) {
// 每秒允许 2 个请求
RateLimiter rateLimiter = RateLimiter.create(2.0);
for (int i = 1; i <= 10; i++) {
// 尝试获取令牌,如果令牌不足则直接返回
if (rateLimiter.tryAcquire()) {
System.out.println("处理请求: " + i);
} else {
System.out.println("请求被限流: " + i);
}
}
}
}
这个示例中,tryAcquire()
方法不会阻塞线程,如果令牌不足,会立即返回 false
。
5. RateLimiter 的应用场景
-
API 限流:防止 API 被恶意请求或突发流量打垮。
-
资源保护:限制对数据库、文件系统等共享资源的访问速率。
-
流量控制:在微服务架构中,限制服务之间的调用速率。
-
任务调度:控制任务处理的速率,确保系统负载均衡。
6. RateLimiter 的优缺点
-
优点:
-
简单易用,集成方便。
-
支持突发流量和预热机制。
-
高性能,适合高并发场景。
-
-
缺点:
-
单机限流,无法直接支持分布式限流。
-
需要根据实际场景调整参数,否则可能导致限流效果不理想。
-
7. 分布式限流
如果需要在分布式系统中实现限流,可以使用以下方案:
-
Redis + Lua 脚本:通过 Redis 的原子操作实现分布式限流。
-
Sentinel:阿里巴巴开源的分布式限流组件。
-
Nginx 限流:通过 Nginx 的限流模块实现网关层限流。
8. Spring Cloud Sentinel RateLimiter 配置
在 Spring Boot 项目中集成 Sentinel 时,可以通过 @SentinelResource
注解来定义受保护的资源,并在 Sentinel 控制台中配置限流规则。
java复制
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@GetMapping("/hello")
@SentinelResource(value = "helloResource", blockHandler = "handleBlockedRequest")
public String hello() {
return "Hello, Sentinel!";
}
public String handleBlockedRequest(Throwable throwable) {
return "Request has been blocked!";
}
}
通过以上方法,你可以使用 RateLimiter
或 Sentinel 在 Java 中实现高效的限流功能。