Infinispan 缓存
默认情况下,Quarkus Cache 使用 Caffeine 作为后端。也可以使用 Infinispan 代替。
此技术被认为是预览版。 在预览版中,不保证向后兼容性和在生态系统中的存在。特定改进可能需要更改配置或 API,并且正在计划成为稳定版。欢迎在我们的邮件列表上提供反馈,或在我们的GitHub 问题跟踪器中提交问题。 有关可能的完整状态列表,请查看我们的常见问题解答条目。 |
Infinispan 作为缓存后端
当使用 Infinispan 作为 Quarkus 缓存的后端时,每个缓存项都将存储在 Infinispan 中。
-
后端使用<default> Infinispan 客户端(除非另有配置),因此请确保其配置已正确设置(或使用Infinispan 开发服务)。
-
键和值都使用 Protobuf 和 Protostream 进行编组。
使用 Infinispan 后端
首先,将 quarkus-infinispan-cache
扩展添加到您的项目中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-cache</artifactId>
</dependency>
implementation("io.quarkus:quarkus-infinispan-cache")
然后,按照Quarkus 缓存指南中的详细说明,使用 @CacheResult
和其他缓存注解。
@GET
@Path("/{keyElement1}/{keyElement2}/{keyElement3}")
@CacheResult(cacheName = "expensiveResourceCache")
public ExpensiveResponse getExpensiveResponse(@PathParam("keyElement1") @CacheKey String keyElement1,
@PathParam("keyElement2") @CacheKey String keyElement2, @PathParam("keyElement3") @CacheKey String keyElement3,
@QueryParam("foo") String foo) {
invocations.incrementAndGet();
ExpensiveResponse response = new ExpensiveResponse();
response.setResult(keyElement1 + " " + keyElement2 + " " + keyElement3 + " too!");
return response;
}
@POST
@CacheInvalidateAll(cacheName = "expensiveResourceCache")
public void invalidateAll() {
}
配置 Infinispan 后端
Infinispan 后端使用 <default>
Infinispan 客户端。有关访问 Infinispan 的配置,请参阅Infinispan 参考。
在开发模式下,您可以使用Infinispan 开发服务。 |
如果您想为缓存使用另一个 Infinispan,请按如下方式配置 client-name
。
quarkus.cache.infinispan.client-name=another
编组
在 Quarkus 中与 Infinispan 交互时,您可以轻松地在缓存中存储或检索数据时序列化和反序列化 Java 原始类型。Infinispan 不需要额外的编组配置。
@CacheResult(cacheName = "weather-cache") (1)
public String getDailyForecast(String dayOfWeek, int dayOfMonth, String city) { (2)
return dayOfWeek + " will be " + getDailyResult(dayOfMonth % 4) + " in " + city;
}
1 | 请求将此方法执行缓存到 'weather-cache' 中 |
2 | 键结合了 String dayOfWeek、int dayOfMonth 和 String city。关联的值是 String 类型。 |
Quarkus 默认在 Infinispan 中使用 Protobuf 进行数据序列化。Infinispan 建议使用 Protobuf 作为组织数据的首选方式。因此,在使用普通 Java 对象 (POJO) 时,用户需要为 Infinispan 中的编组提供 schema。
编组 Java 类型
假设我们想使用 java.time.LocalDate
创建一个复合键。
@CacheResult(cacheName = "weather-cache") (1)
public String getDailyForecast(LocalDate date, String city) { (2)
return date.getDayOfWeek() + " will be " + getDailyResult(date.getDayOfMonth() % 4) + " in " + city;
}
1 | 请求将此方法执行的响应缓存到 'weather-cache' 中 |
2 | 键结合了 java.util.LocalDate 日期和 String city。关联的值是 'String' 类型。 |
由于 Infinispan 在 Quarkus 中默认使用 Protobuf 对数据进行序列化,执行该代码将导致以下错误。
java.lang.IllegalArgumentException:
No marshaller registered for object of Java type java.time.LocalDate
Protobuf 本身不知道如何编组 java.time.LocalDate
。幸运的是,Protostream 使用 @ProtoAdapter
和 @ProtoSchema
为此问题提供了简单的解决方案。
@ProtoAdapter(LocalDate.class)
public class LocalDateAdapter {
@ProtoFactory
LocalDate create(String localDate) {
return LocalDate.parse(localDate);
}
@ProtoField(1)
String getLocalDate(LocalDate localDate) {
return localDate.toString();
}
}
@ProtoSchema(includeClasses = LocalDateAdapter.class, schemaPackageName = "quarkus")
public interface Schema extends GeneratedSchema {
}
编组您的 POJO
与 Java 类型一样,在使用 POJO 作为键或值时,您可以遵循此方法。
@CacheResult(cacheName = "my-cache") (1)
public ExpensiveResponse requestApi(String id) { (2)
// very expensive call
return new ExpensiveResponse(...);
}
1 | 请求将此方法执行的响应缓存到 'my-cache' 中 |
2 | 键是 String 。关联的值是 org.acme.ExpensiveResponse 类型。 |
在这种情况下,您需要使用 @Proto
和 @ProtoSchema
为您的 Java 类型定义 schema。此 schema 可以包含您在 Quarkus 应用程序中使用的所有类型和适配器。
@Proto
public record ExpensiveResponse(String result) {
}
@ProtoSchema(includeClasses = { ExpensiveResponse.class })
interface Schema extends GeneratedSchema {
}
在Infinispan 参考的“基于注解的序列化”部分了解更多信息。
过期
您可以选择配置两个数据过期属性:寿命 (lifespan) 和最大空闲时间 (max-idle)。
寿命
在 Infinispan 中,寿命 (lifespan) 是一个配置参数,它确定了一个条目(或对象)自创建或上次访问以来在缓存中可以存在的最长时间,之后它将被视为已过期并从缓存中移除。
当您为 Infinispan 缓存中的条目配置 寿命 (lifespan) 参数时,您指定了一个时间间隔。在条目添加到缓存或被访问(读取或写入)后,它的寿命倒计时就开始了。如果自条目创建或上次访问以来经过的时间超过了指定的“寿命”间隔,该条目将被视为已过期,并有资格被从缓存中驱逐。
quarkus.cache.infinispan.my-cache.lifespan=10s
最大空闲时间
当您为 Infinispan 缓存中的条目配置 最大空闲时间 (max-idle) 参数时,您指定了一个时间间隔。在缓存中的某个条目被访问(读取或写入)后,如果在指定的时间间隔内没有对该条目进行后续访问,则认为该条目处于空闲状态。一旦空闲时间超过 最大空闲时间 (max-idle) 间隔,该条目将被视为已过期,并可能被从缓存中驱逐。
quarkus.cache.infinispan.my-cache.max-idle=100s
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
用于与 Infinispan 通信的命名 Infinispan 客户端的名称。如果未设置,则使用默认的 Infinispan 客户端。 环境变量: 显示更多 |
字符串 |
|
类型 |
默认 |
|
存储在缓存中的项目的默认寿命。 环境变量: 显示更多 |
||
存储在缓存中的项目的默认最大空闲时间。 环境变量: 显示更多 |
关于 Duration 格式
要编写持续时间值,请使用标准的 您还可以使用简化的格式,以数字开头
在其他情况下,简化格式将被转换为
|