获取 IllegalArgumentException:尝试添加包含 AtomicInteger int redis 缓存的数据时无法将 String 转换为 AtomicInteger
Posted
技术标签:
【中文标题】获取 IllegalArgumentException:尝试添加包含 AtomicInteger int redis 缓存的数据时无法将 String 转换为 AtomicInteger【英文标题】:Getting an IllegalArgumentException: Cannot convert String to AtomicInteger when trying to add data that contains an AtomicInteger int redis cache 【发布时间】:2022-01-05 09:44:13 【问题描述】:我正在尝试将数据模型添加到 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 缓存的最简单方法,具有生存时间和多个速率
【问题讨论】:
【参考方案1】:抛出异常是因为 Spring Data Redis 在加载模型时不知道如何将存储在 Redis 中的字节数组反序列化为 AtomicInteger
类型。您需要为此注册一个数据类型转换器。
这里是示例数据类型转换器:
@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 的通信需要时间(即使仅在毫秒范围内),因此该值被另一台服务器更新的可能性远非零。如果这种偏差对于用例来说是可以的,这可能不是问题。
我还建议查看一些有助于实现请求限制的现有库。下面是一些例子:
-
Throttling a Rest API in Java
Rate Limiting a Spring API Using Bucket4j
Implementing Throttling in Java (Spring Boot)
【讨论】:
非常感谢您的回答以及有关节流的更多信息。我确实看过他们。但是我之所以这样做是因为 URL 是一个参数,在一个对象中,测试节流,然后使用 URL 调用。以上是关于获取 IllegalArgumentException:尝试添加包含 AtomicInteger int redis 缓存的数据时无法将 String 转换为 AtomicInteger的主要内容,如果未能解决你的问题,请参考以下文章
插件 [ingest-geoip] 是为 Elasticsearch 6.2.4 版构建的,但 6.5.0 版正在运行