feat:修改ratelimiter的重复创建问题

This commit is contained in:
lilong 2024-03-15 18:22:03 +08:00
parent 10cfb0fc56
commit c2a13cabf6
2 changed files with 14 additions and 26 deletions

View File

@ -1,31 +1,22 @@
package cn.axzo.pokonyan.client; package cn.axzo.pokonyan.client;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
public interface RateLimiter { public interface RateLimiter {
/** /**
* 尝试获得锁, 获取失败则返回Optional.empty() * 尝试获得锁, 获取失败则返回Optional.empty()
* 如果获取锁成功. 则返回Optional<Permit>. 同时计数器增加 * 如果获取锁成功. 则返回Optional<Permit>. 同时计数器增加
* Permit支持取消 * Permit支持取消
*
* @param value 业务标识
* @return * @return
*/ */
boolean tryAcquire(Object value); boolean tryAcquire();
/** /**
* 获取窗口类型 * 获取窗口类型

View File

@ -24,12 +24,13 @@ public class RedisRateLimiterImpl implements RateLimiter {
private LimitRule limitRule; private LimitRule limitRule;
private WindowType windowType; private WindowType windowType;
private RRateLimiter rateLimiter;
@Builder @Builder
RedisRateLimiterImpl(RedissonClient redissonClient, RedisRateLimiterImpl(RedissonClient redissonClient,
WindowType windowType, WindowType windowType,
String limiterKey, String limiterKey,
LimitRule limitRule, LimitRule limitRule) {
Integer maxWindowDurationHour) {
Objects.requireNonNull(redissonClient); Objects.requireNonNull(redissonClient);
Objects.requireNonNull(windowType); Objects.requireNonNull(windowType);
Objects.requireNonNull(limitRule); Objects.requireNonNull(limitRule);
@ -43,11 +44,16 @@ public class RedisRateLimiterImpl implements RateLimiter {
this.limitRule = limitRule; this.limitRule = limitRule;
this.limiterKey = limiterKey; this.limiterKey = limiterKey;
this.rateLimiterWorker = buildWorker(windowType); this.rateLimiterWorker = buildWorker(windowType);
String key = buildRedisKey();
RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
rateLimiter.trySetRate(RateType.OVERALL, limitRule.getPermits(), limitRule.getSeconds(), RateIntervalUnit.SECONDS);
this.rateLimiter = rateLimiter;
} }
@Override @Override
public boolean tryAcquire(Object value) { public boolean tryAcquire() {
return rateLimiterWorker.tryAcquire(value); return rateLimiterWorker.tryAcquire();
} }
@Override @Override
@ -62,10 +68,9 @@ public class RedisRateLimiterImpl implements RateLimiter {
throw new RuntimeException(String.format("unsupported window type, window type = %s", windowType)); throw new RuntimeException(String.format("unsupported window type, window type = %s", windowType));
} }
private String buildRedisKey(Object value) { private String buildRedisKey() {
String hash = Hashing.murmur3_128().newHasher() String hash = Hashing.murmur3_128().newHasher()
.putString(limiterKey, Charsets.UTF_8) .putString(limiterKey, Charsets.UTF_8)
.putString(String.valueOf(value), Charsets.UTF_8)
.hash() .hash()
.toString(); .toString();
@ -81,14 +86,7 @@ public class RedisRateLimiterImpl implements RateLimiter {
* </pre> * </pre>
*/ */
class SlidingWindowRateLimiter implements RateLimiterWorker { class SlidingWindowRateLimiter implements RateLimiterWorker {
public boolean tryAcquire(Object value) { public boolean tryAcquire() {
String key = buildRedisKey(value);
RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
if (!rateLimiter.isExists()) {
rateLimiter.trySetRate(RateType.OVERALL, limitRule.getPermits(), limitRule.getSeconds(), RateIntervalUnit.SECONDS);
}
return rateLimiter.tryAcquire(1); return rateLimiter.tryAcquire(1);
} }
} }
@ -97,9 +95,8 @@ public class RedisRateLimiterImpl implements RateLimiter {
/** /**
* 尝试获取令牌 * 尝试获取令牌
* *
* @param value
* @return 如果获取成功则返回true, 失败则为false * @return 如果获取成功则返回true, 失败则为false
*/ */
boolean tryAcquire(Object value); boolean tryAcquire();
} }
} }