【问题标题】:Using resilience4j to rate limit based on API Key使用resilience4j基于API Key进行速率限制
【发布时间】:2021-10-01 03:31:46
【问题描述】:
我正在构建一个 Java REST API,它要求客户端使用 api 密钥才能访问。我想实现基于 API 密钥的速率限制,以便单个 api 在给定的时间范围内不能多次使用该 api。我一直在寻找为此使用弹性4j,但我似乎无法找到弹性4j是否支持基于IP地址或api密钥等标准实施速率限制,而不仅仅是一般的速率限制。有谁知道这是否可能,或者知道任何显示如何做到这一点的资源?谢谢。
【问题讨论】:
标签:
java
rest
rate-limiting
resilience4j
【解决方案1】:
您需要为每个 IP/apiKey 提供一个 RateLimiter 实例,而不是为所有 IP/apiKey 提供一个 RateLimiter 实例。
请参阅以下指南:
// Define one instance of LimiterManager ( Singleton | ApplicationScoped )
// NOTES: Reuse this instance
LimiterManager limiterManager = new LimiterManager();
String apiKey = "abc"; // // Get apiKey from current client request
final RateLimiter rateLimiter = limiterManager.getLimiter(apiKey);
// You can use other RateLimiter.decorateXXX depends on your logic
Runnable runnable = RateLimiter.decorateRunnable(rateLimiter, new Runnable() {
@Override
public void run() {
// TODO: Your allowed code here
}
});
Try.runRunnable(runnable).onFailure(
error -> System.out.print(error)
);
// Define LimiterManager utility class
public static class LimiterManager {
final ConcurrentMap<String, RateLimiter> keyRateLimiters = new ConcurrentHashMap<String, RateLimiter>();
final RateLimiterConfig config = RateLimiterConfig.custom().timeoutDuration(Duration.ofMillis(100))
.limitRefreshPeriod(Duration.ofSeconds(1))
.limitForPeriod(3) // Max 3 accesses per 1 second
.build();
public RateLimiter getLimiter(String apiKey) {
return keyRateLimiters.compute(apiKey, (key, limiter) -> {
return (limiter == null) ? RateLimiter.of(apiKey, config) : limiter;
});
}
}