我正在嘗試將資料模型添加到 redis 快取。當我取出模型時,出現例外
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [byte[]] to type [java.util.concurrent.atomic.AtomicInteger] for value '{53}'; nested exception is java.lang.IllegalArgumentException: Cannot convert String [5] to target class [java.util.concurrent.atomic.AtomicInteger]] with root cause
該模型是
@RedisHash(value = "ThottleRate", timeToLive = 5)
public class ThottleRate implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String url;
private AtomicInteger rate;
public ThottleRate(String url, int rate) {
super();
this.url = url;
this.rate = new AtomicInteger(rate);
}
public boolean isAllowed(){
if(this.rate.decrementAndGet() <= 0) {
return false;
}
return true;
}
呼叫代碼是
try {
option = throttleRateRepository.findById(url);
ThottleRate rate = option.get();
allow = rate.isAllowed();
} catch(NoSuchElementException e) {
throttleRateRepository.save(new ThottleRate(url, 5));
allow = true;
}
我想要做的是使用 redis 快取來限制功能。它有一段時間存在,并且在此期間可以多次訪問 url。
但是當電話是
option = throttleRateRepository.findById(url);
這會拋出 IllegalArgumentException
這似乎是使用 redis 快取的最簡單方法,具有生存時間和多種速率
uj5u.com熱心網友回復:
拋出例外是因為 Spring Data Redis 不知道如何AtomicInteger在加載模型時反序列化存盤在 Redis 中的位元組陣列。您需要為此注冊一個資料型別轉換器。
這是示例資料型別轉換器:
@Component
@ReadingConverter
public class BytesToAtomicIntegerConverter implements Converter<byte[], AtomicInteger> {
@Override
public AtomicInteger convert(byte[] source) {
if (ObjectUtils.isEmpty(source)) {
return null;
}
int n = NumberUtils.parseNumber(
new String(source, StandardCharsets.UTF_8), Integer.class);
return new AtomicInteger(n);
}
}
可以通過將此 bean 添加到 SpringBoot 配置來向 Spring Data Redis 注冊:
@Bean
public RedisCustomConversions redisCustomConversions(
BytesToAtomicIntegerConverter converter) {
return new RedisCustomConversions(List.of(converter));
}
一旦資料轉換器被注冊,錯誤就會消失。
在實施此類解決方案時,您必須牢記幾件事。該AtomicInteger欄位在此處用于保持對特定人員的請求計數。如果有多個服務器為請求提供服務,那么不同的服務器最終將在本地記憶體中的該欄位中存盤不同的值。由于與 Redis 的通信需要時間(即使僅在幾毫秒范圍內),因此該值被另一臺服務器更新的可能性遠非零。如果這種偏差適用于用例,這可能不是問題。
我還建議查看一些可以幫助實作請求限制的現有庫。以下是一些示例:
- 在 Java 中限制 Rest API
- 使用 Bucket4j 限制 Spring API 的速率
- 在 Java 中實作節流 (Spring Boot)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/368628.html
標籤:爪哇 春天 Redis 节流 spring-data-redis
