Using the Infinispan Client

Prerequisites

include::./_includes/prerequisites.adoc[]* 正在运行的 Docker 环境

Architecture

在本指南中,我们将使用 Infinispan RemoteCache APIgetAsyncputAsync 操作来公开一个 Greeting Rest API,用于创建和显示问候消息。

我们将使用 Quarkus Infinispan Client 扩展来连接到 Infinispan 进行交互。

Solution

我们建议您遵循接下来的部分中的说明,按部就班地创建应用程序。然而,您可以直接跳到完成的示例。

克隆 Git 存储库: git clone $${quickstarts-base-url}.git,或下载 $${quickstarts-base-url}/archive/main.zip[存档]。

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

Creating the Maven Project

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

CLI
quarkus create app {create-app-group-id}:{create-app-artifact-id} \
    --no-code
cd {create-app-artifact-id}

要创建一个 Gradle 项目,添加 --gradle--gradle-kotlin-dsl 选项。 有关如何安装和使用 Quarkus CLI 的详细信息,请参见 Quarkus CLI 指南。

Maven
mvn {quarkus-platform-groupid}:quarkus-maven-plugin:{quarkus-version}:create \
    -DprojectGroupId={create-app-group-id} \
    -DprojectArtifactId={create-app-artifact-id} \
    -DnoCode
cd {create-app-artifact-id}

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

适用于 Windows 用户:

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

  • 如果使用 Powershell,将 -D 参数用双引号引起来,例如 "-DprojectArtifactId={create-app-artifact-id}"

此命令生成一个新项目,导入 Infinispan Client 扩展。

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

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

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

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 构建中强制要求启用基于注释序列化的文件生成

Creating the 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 是 Infinispan 的基于 Protobuf 数据格式的序列化库。使用基于注释的 API,我们将数据存储为 Protobuf 格式。

Creating the 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 包括带 Greeting 注释的 `@ProtoSchema`pojo
2 扩展 GeneratedSchema Protostream API 接口

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

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

syntax = "proto3";

message Greeting {

   optional string name = 1;

   optional string message = 2;
}

Creating the Infinispan Greeting Resource

创建 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 注释来使用高速缓存。如果高速缓存不存在,将使用默认配置 on first access 创建。
2 Inject the RemoteCache
3 将问候 ID 作为键,将问候 pojo 作为值
4 通过 ID(作为键)获取问候

Creating the test class

编辑 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!\"}"));
    }
}

Get it running

我们只需要使用以下内容运行应用程序:

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

由于 Dev 服务,我们应该让 Infinispan 服务器运行。我们可以通过 http://localhost:8080/q/dev/ 访问 Dev 服务 UI。Dev UI 应该显示 Infinispan UI 面板。

dev ui infinispan

单击 Web 控制台链接并使用 adminpassword 默认凭据进行日志记录。Quarkus 已将 Protobuf 模式上传到模式选项卡,该模式用于使用 Protobuf 在服务器上编组 Greeting POJO。查看 Infinispan Dev Services Guide 以了解更多信息。

Interacting with the Greeting Service

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

Creating a Greeting Message

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

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

该服务应使用 Greeting added! 消息进行响应。

Displaying a Greeting Message

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

curl  http://localhost:8080/greeting/quarkus

该服务应使用以下 json 内容进行响应。

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

Display the cache and content with the Infinispan Server Console

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

infinispan console client guide

Configuring for production

至此,Quarkus 使用 Infinispan Dev 服务来运行 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

## Docker 4 Mac workaround. Uncomment only if you are using Docker for Mac.
## Read more about it in the Infinispan Reference Guide
# %prod.quarkus.infinispan-client.client-intelligence=BASIC 4
1 设置 Infinispan 服务器地址列表,以逗号分隔
2 Sets the authentication username
3 Sets the authentication password
4 设置客户端情报。如果您在 Mac 上使用 Docker,请使用 BASIC 作为一种解决方法。

客户端情报的变化会影响您在生产中的性能。除非对您的情况绝对必要,否则不要更改客户端情报。在 Infinispan Client extension reference guide 中阅读更多内容。

Packaging and running in JVM mode

您可以将应用程序作为常规 jar 文件运行。

首先,我们需要对其进行打包:

CLI
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

此命令将启动一个 Infinispan 实例来执行测试。

然后运行它:

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

Running Native

您还可以从此应用程序创建本机可执行程序,而无需进行任何源代码更改。本机可执行程序消除了对 JVM 的依赖:在本机可执行程序中包含了在目标平台上运行应用程序所需的一切,从而允许应用程序以最小的资源开销运行。

编译本机可执行程序需要花费更长时间,因为 GraalVM 会执行额外的步骤来删除不必要的代码路径。使用 native 配置文件来编译本机可执行程序:

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

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

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

Going further

要了解有关 Quarkus Infinispan 扩展的更多信息,请查看 the Infinispan Client extension reference guide