编辑此页面

使用 Infinispan 客户端

本指南将演示 Quarkus 应用程序如何使用 Infinispan 客户端扩展连接到 Infinispan 服务器。

先决条件

要完成本指南,您需要

  • 大约 15 分钟

  • 一个 IDE

  • 已安装 JDK 17+ 并正确配置了 JAVA_HOME

  • Apache Maven 3.9.9

  • 如果您想使用它,可以选择 Quarkus CLI

  • 如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置

  • 一个可用的 Docker 环境

架构

在本指南中,我们将通过使用 Infinispan RemoteCache API 以及 getAsyncputAsync 操作来公开一个 Greeting REST API,以创建和显示问候消息。

我们将使用 Quarkus Infinispan 客户端扩展来连接并与 Infinispan 进行交互。

解决方案

我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。

克隆 Git 存储库:git clone https://github.com/quarkusio/quarkus-quickstarts.git,或者下载一个 存档

解决方案位于 infinispan-client-quickstart 目录中。

创建 Maven 项目

首先,我们需要一个新项目。使用以下命令创建一个新项目

CLI
quarkus create app org.acme:infinispan-client-quickstart \
    --extension='infinispan-client,rest' \
    --no-code
cd infinispan-client-quickstart

要创建 Gradle 项目,请添加 --gradle--gradle-kotlin-dsl 选项。

有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.24.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=infinispan-client-quickstart \
    -Dextensions='infinispan-client,rest' \
    -DnoCode
cd infinispan-client-quickstart

要创建 Gradle 项目,请添加 -DbuildTool=gradle-DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户

  • 如果使用 cmd,(不要使用反斜杠 \ 并将所有内容放在同一行上)

  • 如果使用 Powershell,请将 -D 参数用双引号括起来,例如 "-DprojectArtifactId=infinispan-client-quickstart"

此命令会生成一个新项目,并导入 Infinispan 客户端扩展。

如果您已经配置了 Quarkus 项目,可以通过在项目根目录中运行以下命令,将 infinispan-client 扩展添加到您的项目中

CLI
quarkus extension add infinispan-client
Maven
./mvnw quarkus:add-extension -Dextensions='infinispan-client'
Gradle
./gradlew addExtension --extensions='infinispan-client'

这会将以下内容添加到您的构建文件中

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-infinispan-client</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-infinispan-client")
annotationProcessor 'org.infinispan.protostream:protostream-processor:4.6.1.Final' (1)
1 在 Gradle 构建中是必需的,以启用基于注释的序列化文件生成

创建 Greeting POJO

我们将使用 Greeting POJO 来模拟我们的增量。创建 src/main/java/org/acme/infinispan/client/Greeting.java 文件,内容如下:

package org.acme.infinispan.client;

import org.infinispan.protostream.annotations.Proto;

@Proto (1)
public record Greeting(String name, String message) {} (2)
1 您只需要一个注解来标记要由 Protostream 编组的记录

请注意,我们不会使用 Java 序列化。 Protostream 是一个基于 Protobuf 数据格式的序列化库,它是 Infinispan 的一部分。使用基于注解的 API,我们将以 Protobuf 格式存储数据。

创建 Greeting Schema

我们将使用 GreetingSchema 接口来创建我们的序列化模式。创建 src/main/java/org/acme/infinispan/client/GreetingSchema.java 文件,内容如下:

package org.acme.infinispan.client;

import org.infinispan.protostream.GeneratedSchema;
import org.infinispan.protostream.annotations.ProtoSchema;

@ProtoSchema(includeClasses = Greeting.class) (1)
public interface GreetingSchema extends GeneratedSchema { (2)
}
1 包含带有 @ProtoSchema 注解的 Greeting pojo
2 扩展了 GeneratedSchema Protostream API 接口

将在客户端和 Infinispan 服务器端生成并使用的 Protobuf Schema 将具有以下内容:

// File name: GreetingSchema.proto
// Generated from : org.acme.infinispan.client.GreetingSchema

syntax = "proto3";

message Greeting {

   optional string name = 1;

   optional string message = 2;
}

创建 Infinispan Greeting 资源

创建 src/main/java/org/acme/infinispan/client/InfinispanGreetingResource.java 文件,内容如下:

package org.acme.infinispan.client;

import io.quarkus.infinispan.client.Remote;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import org.infinispan.client.hotrod.RemoteCache;

import java.util.concurrent.CompletionStage;

@Path("/greeting")
public class InfinispanGreetingResource {

    @Inject
    @Remote("mycache") (1)
    RemoteCache<String, Greeting> cache; (2)

    @POST
    @Path("/{id}")
    public CompletionStage<String> postGreeting(String id, Greeting greeting) {
        return cache.putAsync(id, greeting) (3)
              .thenApply(g -> "Greeting done!")
              .exceptionally(ex -> ex.getMessage());
    }

    @GET
    @Path("/{id}")
    public CompletionStage<Greeting> getGreeting(String id) {
        return cache.getAsync(id); (4)
    }
}
1 使用 @Remote 注解来使用缓存。如果缓存不存在,它将在 **首次访问时** 以默认配置创建。
2 注入 RemoteCache
3 将问候 ID 作为键,将 Greeting pojo 作为值放入
4 按 ID(作为键)获取问候

创建测试类

编辑 pom.xml 文件以添加以下依赖项:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>

创建 src/test/java/org/acme/infinispan/client/InfinispanGreetingResourceTest.java 文件,内容如下:

package org.acme.infinispan.client;

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
class InfinispanGreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
              .contentType(ContentType.JSON)
              .body("{\"name\":\"Infinispan Client\",\"message\":\"Hello World, Infinispan is up!\"}")
              .when()
              .post("/greeting/quarkus")
              .then()
              .statusCode(200);

        given()
                .when().get("/greeting/quarkus")
                .then()
                .statusCode(200)
                .body(is("{\"name\":\"Infinispan Client\",\"message\":\"Hello World, Infinispan is up!\"}"));
    }
}

开始运行

我们只需要使用以下命令运行应用程序:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

由于 Dev Services 的存在,我们应该已经运行了 Infinispan 服务器。我们可以通过 https://:8080/q/dev/ 访问 Dev Services UI。Dev UI 应该显示 Infinispan UI 面板。

Dev UI Infinispan

点击 Web Console 链接,并使用 adminpassword 默认凭据登录。Quarkus 已在 Schemas 选项卡中上传了在服务器上使用 Protobuf 编组 Greeting POJO 所需的 Protobuf Schema。请查看 Infinispan Dev Services 指南 以了解更多信息。

与 Greeting 服务交互

如上所述,Greeting API 公开了两个 REST 端点。在本节中,我们将介绍如何创建和显示问候消息。

创建问候消息

使用以下命令,我们将创建一个 ID 为 quarkus 的问候消息。

curl -X POST https://:8080/greeting/quarkus -H "Content-Type: application/json" -d '{"name" : "Infinispan Client", "message":"Hello World, Infinispan is up!"}'

服务应响应 Greeting added! 消息。

显示问候消息

使用以下命令,我们将显示 ID 为 quarkus 的问候消息。

curl  https://:8080/greeting/quarkus

服务应响应以下 JSON 内容:

{
  "name" : "Infinispan Client",
  "message" : "Hello World, Infinispan is up!"
}

使用 Infinispan 服务器控制台显示缓存和内容

如果请求的缓存不存在,Quarkus 会在首次访问时创建一个具有默认配置的缓存。我们应该能够重新加载 Infinispan 服务器控制台并显示缓存的内容。Infinispan 服务器控制台使用 Infinispan 服务器 REST API。由于 Protobuf 编码将其转换为 JSON 格式,因此内容可以以 JSON 格式显示。

Infinispan Console

生产环境配置

此时,Quarkus 使用 Infinispan Dev Service 来运行 Infinispan 服务器并配置应用程序。但是,在生产环境中,您将运行自己的 Infinispan(或 Red Hat Data Grid)。

让我们使用以下命令在端口 11222 上启动一个 Infinispan 服务器:

docker run -it -p 11222:11222 -e USER="admin" -e PASS="password" quay.io/infinispan/server:latest

然后,打开 src/main/resources/application.properties 文件并添加:

%prod.quarkus.infinispan-client.hosts=localhost:11222 (1)
%prod.quarkus.infinispan-client.username=admin (2)
%prod.quarkus.infinispan-client.password=password (3)
1 设置 Infinispan 服务器地址列表,用分号分隔
2 设置认证用户名
3 设置认证密码

打包和以 JVM 模式运行

您可以像运行常规 jar 文件一样运行应用程序。

首先,我们需要打包它:

CLI
quarkus build
Maven
./mvnw install
Gradle
./gradlew build
此命令将启动一个 Infinispan 实例来执行测试。

然后运行它

java -jar target/quarkus-app/quarkus-run.jar

原生运行

您也可以在此应用程序上创建原生可执行文件,而无需进行任何源代码更改。原生可执行文件消除了对 JVM 的依赖:运行应用程序所需的一切都包含在可执行文件中,从而使应用程序能够以最小的资源开销运行。

编译原生可执行文件需要更长的时间,因为 GraalVM 会执行额外的步骤来删除不必要的代码路径。使用 native profile 来编译原生可执行文件:

CLI
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

构建完成后,您可以使用以下命令运行可执行文件:

./target/infinispan-client-quickstart-1.0.0-SNAPSHOT-runner

更进一步

要了解更多关于 Quarkus Infinispan 扩展的信息,请参阅 Infinispan 客户端扩展参考指南

相关内容