Use redis key hash tags for redis cluster support.

fixes gh-248
This commit is contained in:
Spencer Gibb
2018-04-02 15:05:22 -04:00
parent 8edc2e025d
commit 39913f03ff
2 changed files with 23 additions and 7 deletions

View File

@@ -10,6 +10,9 @@ import javax.validation.constraints.Min;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -18,9 +21,6 @@ import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* See https://stripe.com/blog/rate-limiters and
* https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d#file-1-check_request_rate_limiter-rb-L11-L34
@@ -102,11 +102,8 @@ public class RedisRateLimiter extends AbstractRateLimiter<RedisRateLimiter.Confi
int burstCapacity = routeConfig.getBurstCapacity();
try {
// Make a unique key per user.
String prefix = "request_rate_limiter." + id;
List<String> keys = getKeys(id);
// You need two Redis keys for Token Bucket.
List<String> keys = Arrays.asList(prefix + ".tokens", prefix + ".timestamp");
// The arguments to the LUA script. time() returns unixtime in seconds.
List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",
@@ -141,6 +138,19 @@ public class RedisRateLimiter extends AbstractRateLimiter<RedisRateLimiter.Confi
return Mono.just(new Response(true, -1));
}
static List<String> getKeys(String id) {
// use `{}` around keys to use Redis Key hash tags
// this allows for using redis cluster
// Make a unique key per user.
String prefix = "request_rate_limiter.{" + id;
// You need two Redis keys for Token Bucket.
String tokenKey = prefix + "}.tokens";
String timestampKey = prefix + "}.timestamp";
return Arrays.asList(tokenKey, timestampKey);
}
@Validated
public static class Config {
@Min(1)

View File

@@ -71,6 +71,12 @@ public class RedisRateLimiterTests extends BaseWebClientTests {
response = rateLimiter.isAllowed(routeId, id).block();
assertThat(response.isAllowed()).as("steady state # %s is allowed", replenishRate).isFalse();
}
@Test
public void keysUseRedisKeyHashTags() {
assertThat(RedisRateLimiter.getKeys("1"))
.containsExactly("request_rate_limiter.{1}.tokens", "request_rate_limiter.{1}.timestamp");
}
@EnableAutoConfiguration
@SpringBootConfiguration