Infinispan Cache

默认情况下,Quarkus Cache 使用 Caffeine 作为后端。你可以改用 Infinispan。 :iokays-category: quarkus :iokays-path: modules/ROOT/pages/_includes/extension-status.adoc :keywords: Quarkus, 中文文档, 编程技术

该技术被认为是 {extension-status}。 有关可能状态的完整列表,请查看我们的 FAQ entry.

Infinispan as cache backend

将 Infinispan 用作 Quarkus 缓存的后端时,每个缓存项都将存储在 Infinispan 中:

  • 后端使用 @13 Infinispan 客户端(除非配置不同),因此请确保其配置已相应设置(或使用 @14)。

  • 键和值都使用 Protostream 和 protobuf 进行计算。

Use the Infinispan backend

首先,将 @15 扩展添加到你的项目:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-infinispan-cache</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-infinispan-cache")

然后,使用 @16 和其他缓存注释,正如 @17 中详细说明的那样:

@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() {

}

Configure the Infinispan backend

Infinispan 后端使用 @18 Infinispan 客户端. 请参阅 @19 以了解配置对 Infinispan 的访问权限。

在开发模式中,你可以使用 @20.

如果你想为你的缓存使用另一个 Infinispan,请按照如下方式配置 @21:

quarkus.cache.infinispan.client-name=another

Marshalling

在 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`星期几、`int`本月几日和 `String`城市。关联的值类型为 `String

Quarkus 默认使用协议缓冲区对 Infinispan 中的数据进行序列化。Infinispan 建议使用协议缓冲区作为首选的数据结构方式。因此,在使用纯旧 Java 对象 (POJO) 时,用户需要在 Infinispan 中提供编组架构。

Marshalling Java types

我们假设要使用 `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`城市。关联的值的类型为“String”。

由于 Infinispan 在 Quarkus 中默认使用协议缓冲区序列化数据,因此执行代码会产生以下错误:

java.lang.IllegalArgumentException:
No marshaller registered for object of Java type java.time.LocalDate

协议缓冲区本身不知道如何编组 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 {
}

Marshalling your POJOs

与 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 类型定义架构。该架构可以包含 Quarkus 应用程序中使用的所有类型和适配器。

@Proto
public record ExpensiveResponse(String result) {
}

@ProtoSchema(includeClasses = { ExpensiveResponse.class })
interface Schema extends GeneratedSchema {
}

在基于注解的序列化部分的 Infinispan reference中阅读更多相关信息。

Expiration

您可以配置两个数据过期属性: lifespan*和 *max-idle

Lifespan

在 Infinispan 中,*lifespan*指一个配置参数,用于确定一项(或一个对象)在缓存中创建或在标记为过期并从缓存中移除之前,在该缓存中可以驻留的最长时间。

当您为 Infinispan 缓存中的条目配置 *lifespan*参数时,您指定了一个时间持续时间。一项被添加到缓存中或被访问(读取或写入)后,便开始倒计时其生命周期。如果自条目创建或最后访问以来的时间超出了指定“生命周期”持续时间,那么该条目将被视为已过期,且符合从缓存中驱逐的条件。

quarkus.cache.infinispan.my-cache.lifespan=10s

Max Idle

当您为 Infinispan 缓存中的条目配置 *max-idle*参数时,您指定了一个时间持续时间。一项在缓存中被访问(读取或写入)后,如果在指定持续时间内没有后续访问该项,那么该项会被视为闲置。一旦闲置时间超过 *max-idle*持续时间,那么该条目将被视为已过期,且符合从缓存中驱逐的条件。

quarkus.cache.infinispan.my-cache.max-idle=100s

Unresolved include directive in modules/ROOT/pages/cache-infinispan-reference.adoc - include::../../../target/quarkus-generated-doc/config/quarkus-infinispan-cache.adoc[]