Infinispan Client
Infinispan is a distributed, in-memory key/value store that provides Quarkus applications with a highly configurable and independently scalable data layer. This extension gives you client functionality that connects applications running on Quarkus with remote Infinispan clusters.
To find out more about Infinispan, visit the Infinispan documentation.
ソリューション
We recommend that you complete each step in the following sections to create the application. However, you can proceed directly to the completed solution as follows:
Clone the Git repository: git clone https://github.com/quarkusio/quarkus-quickstarts.git
or download an archive. Locate the solution in the infinispan-client-quickstart
directory.
Adding the Infinispan client extension
Run the following command in the base directory of your Quarkus project to add the infinispan-client
extension:
quarkus extension add 'infinispan-client'
./mvnw quarkus:add-extension -Dextensions="infinispan-client"
./gradlew addExtension --extensions="infinispan-client"
This command adds the following dependency to your build file:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-infinispan-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-infinispan-client")
Infinispanクライアントの設定
src/main/resources
ディレクトリの application.properties
をテキストエディタで開いて下さい。
Note that Infinispan documentation refers to a hotrod-client.properties
file. You can configure the Infinispan client with either properties file but application.properties
always takes priority over hotrod-client.properties
.
Additionally, you cannot update configuration properties at runtime. If you modify application.properties
or hotrod-client.properties
, you must rebuild the application before those changes take effect.
Connecting to Infinispan clusters
Add the following properties to connect to Infinispan Server:
# Infinispan Server address
quarkus.infinispan-client.server-list=localhost:11222
# Authentication
quarkus.infinispan-client.auth-username=admin
quarkus.infinispan-client.auth-password=password
# Infinispan client intelligence
# Use BASIC as a Docker for Mac workaround
quarkus.infinispan-client.client-intelligence=BASIC
To use the Infinispan client extension, you need at least one running instance of Infinispan Server.
Check out our 5-minute Getting stated with Infinispan tutorial to run Infinispan Server locally.
Infinispan Server also enables authentication and security authorization by default, so you need to create a user with permissions.
-
If you run the Infinispan Server image, pass the
USER="admin"
andPASS="password"
parameters. -
If you run the bare metal distribution, use the Command Line Interface (CLI) as follows:
$ ./bin/cli.sh user create admin -p password
認証メカニズム
You can use the following authentication mechanisms with the Infinispan client:
-
DIGEST-MD5
-
PLAIN (recommended only in combination with TLS encryption)
-
EXTERNAL
Other authentication mechanisms, such as SCRAM and GSSAPI, are not yet verified with the Infinispan client.
認証の設定についての詳しい情報は Hot Rod Endpoint Authentication Mechanisms に存在します。
You must configure authentication in the |
シリアライゼーション(Key Value型のサポート)
By default, the client will support keys and values of the following types: byte[], primitive wrappers (e.g. Integer, Long, Double), String, Date and Instant. User types require some additional steps that are detailed here. Let’s say we have the following user classes:
public class Author {
private final String name;
private final String surname;
public Author(String name, String surname) {
this.name = Objects.requireNonNull(name);
this.surname = Objects.requireNonNull(surname);
}
// Getter/Setter/equals/hashCode/toString は省略
}
public class Book {
private final String title;
private final String description;
private final int publicationYear;
private final Set<Author> authors;
private final BigDecimal price;
public Book(String title, String description, int publicationYear, Set<Author> authors, BigDecimal price) {
this.title = Objects.requireNonNull(title);
this.description = Objects.requireNonNull(description);
this.publicationYear = publicationYear;
this.authors = Objects.requireNonNull(authors);
this.price = price;
}
// Getter/Setter/equals/hashCode/toString は省略
}
ユーザ型のシリアライズは、https://github.com/infinispan/protostream[Protostream]と呼ばれるprotobufをベースにしたライブラリを使用します。
Infinispan caches can store keys and values in different encodings, but recommend using Protocol Buffers (Protobuf). For more information see our Cache Encoding and Marshalling guide. |
アノテーションに基づくシリアライゼーション
これは、ユーザクラスに protostream アノテーションを追加することで自動的に行えます。加えて、初期化子がアノテーションされたインターフェースが1つ必要です。これは、サポートするクラスの生成方法を制御します。
ここでは、先述のクラスをどのように変更するかの例を示します。
@ProtoFactory
public Author(String name, String surname) {
this.name = Objects.requireNonNull(name);
this.surname = Objects.requireNonNull(surname);
}
@ProtoField(number = 1)
public String getName() {
return name;
}
@ProtoField(number = 2)
public String getSurname() {
return surname;
}
@ProtoFactory
public Book(String title, String description, int publicationYear, Set<Author> authors) {
this.title = Objects.requireNonNull(title);
this.description = Objects.requireNonNull(description);
this.publicationYear = publicationYear;
this.authors = Objects.requireNonNull(authors);
}
@ProtoField(number = 1)
public String getTitle() {
return title;
}
@ProtoField(number = 2)
public String getDescription() {
return description;
}
@ProtoField(number = 3, defaultValue = "-1")
public int getPublicationYear() {
return publicationYear;
}
@ProtoField(number = 4)
public Set<Author> getAuthors() {
return authors;
}
クラスが変更可能なフィールドしかない場合、 ProtoFactory
アノテーションは必要ありません。あなたのクラスが引数なしのコンストラクタを持っていると仮定します。
必要なのは、設定を指定する為のアノテーションを付与した非常にシンプルな GeneratedSchema
インターフェイスだけです。
import org.infinispan.protostream.GeneratedSchema;
import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder;
import org.infinispan.protostream.types.java.math.BigDecimalAdapter;
@AutoProtoSchemaBuilder(includeClasses = { Book.class, Author.class, BigDecimalAdapter.class }, schemaPackageName = "book_sample")
interface BookStoreSchema extends GeneratedSchema {
}
Protostream provides default Protobuf mappers for commonly used types as BigDecimal , included in the org.infinispan.protostream.types package.
|
そこで今回は、含まれるクラスのマーシャラとスキーマを自動生成して、スキーマパッケージに自動で配置します。パッケージは用意する必要はありませんが、Infinispanクエリ機能を利用する場合は生成されたパッケージを知っておく必要があります。
Quarkusでは、 schemaFileName と schemaFilePath 属性は、 AutoProtoSchemaBuilder アノテーションに設定すべきではありません。いずれかを設定すると、ネイティブランタイムエラーが発生します。
|
カスタムシリアライゼーション
前の方法は、ユーザが自分のクラスにアノテーションを付けられる場合のために提案されています。残念ながら、ユーザはキャッシュに入れるすべてのクラスにアノテーションを付けることができないかもしれません。このような場合はスキーマを定義し、自分で独自のマーシャラを作成しなければなりません。
- Protobuf スキーマ
-
2つの方法のいずれかでprotobufスキーマを提供できます。
-
Proto ファイル + プロジェクトの
META-INF
ディレクトリに.proto
ファイルを置けます。これらのファイルは、初期化時に自動的に取り上げられます。library.protopackage book_sample; message Book { required string title = 1; required string description = 2; required int32 publicationYear = 3; // no native Date type available in Protobuf repeated Author authors = 4; requited double price = 5; // no native BigDecimal type available in Protobuf } message Author { required string name = 1; required string surname = 2; }
-
コード +
org.infinispan.protostream.FileDescriptorSource
型の生成されたBeanを定義することにより、ユーザコードで直接protoスキーマを定義できます。@Produces FileDescriptorSource bookProtoDefinition() { return FileDescriptorSource.fromString("library.proto", "package book_sample;\n" + "\n" + "message Book {\n" + " required string title = 1;\n" + " required string description = 2;\n" + " required int32 publicationYear = 3; // no native Date type available in Protobuf\n" + "\n" + " repeated Author authors = 4;\n" + "\n" + " required double price = 5; // no native BigDecimal type available in Protobuf\n" + "}\n" + "\n" + "message Author {\n" + " required string name = 1;\n" + " required string surname = 2;\n" + "}"); }
-
- ユーザマーシャラ
-
最後にすべきことは、proto スキーマで定義された各ユーザクラスの
org.infinispan.protostream.MessageMarshaller
実装を提供することです。このクラスは、上記のコードベースの proto スキーマの定義と同様の方法で@Produces
を介して提供されます。こちらは、Author と Book クラスのマーシャラクラスです。
型名は <protobuf package>.<protobuf message>
と正確に一致している必要があります!AuthorMarshaller.javapublic class AuthorMarshaller implements MessageMarshaller<Author> { @Override public String getTypeName() { return "book_sample.Author"; } @Override public Class<? extends Author> getJavaClass() { return Author.class; } @Override public void writeTo(ProtoStreamWriter writer, Author author) throws IOException { writer.writeString("name", author.getName()); writer.writeString("surname", author.getSurname()); } @Override public Author readFrom(ProtoStreamReader reader) throws IOException { String name = reader.readString("name"); String surname = reader.readString("surname"); return new Author(name, surname); } }
BookMarshaller.javapublic class BookMarshaller implements MessageMarshaller<Book> { @Override public String getTypeName() { return "book_sample.Book"; } @Override public Class<? extends Book> getJavaClass() { return Book.class; } @Override public void writeTo(ProtoStreamWriter writer, Book book) throws IOException { writer.writeString("title", book.getTitle()); writer.writeString("description", book.getDescription()); writer.writeInt("publicationYear", book.getPublicationYear()); writer.writeCollection("authors", book.getAuthors(), Author.class); writer.writeDouble("price", book.getPrice().doubleValue()); } @Override public Book readFrom(ProtoStreamReader reader) throws IOException { String title = reader.readString("title"); String description = reader.readString("description"); int publicationYear = reader.readInt("publicationYear"); Set<Author> authors = reader.readCollection("authors", new HashSet<>(), Author.class); BigDecimal price = BigDecimal.valueOf(reader.readDouble("price")); return new Book(title, description, publicationYear, authors, price); } }
そして、以下のように定義してマーシャラを渡します。
@Produces MessageMarshaller authorMarshaller() { return new AuthorMarshaller(); } @Produces MessageMarshaller bookMarshaller() { return new BookMarshaller(); }
上記のように生成されたMarshallerメソッドは、型なしで MessageMarshaller
を返さなければなりません。さもないと、それが見つかりません。
依存性注入
As you saw above we support the user injecting Marshaller configuration. You can do the inverse with the Infinispan client extension providing injection for RemoteCacheManager
and RemoteCache
objects. There is one global RemoteCacheManager
that takes all the configuration parameters setup in the above sections.
It is very simple to inject these components. All you need to do is to add the @Inject
annotation to the field, constructor or method. In the below code we utilize field and constructor injection.
@Inject SomeClass(RemoteCacheManager remoteCacheManager) {
this.remoteCacheManager = remoteCacheManager;
}
@Inject @Remote("myCache")
RemoteCache<String, Book> cache;
RemoteCacheManager remoteCacheManager;
RemoteCache
宣言に Remote
というオプションのアノテーションが追加されていることにお気づきでしょうか。これは、注入される名前付きキャッシュを指定するための修飾子アノテーションです。このアノテーションは必須ではなく、指定しなかった場合はデフォルトのキャッシュが注入されます。
その他の型は注入のためにサポートされている場合がありますが、詳細については他のセクションを参照してください。 |
Registering Protobuf Schemas with Infinispan Server
You need to register the generated Protobuf schemas with Infinispan Server to perform queries or convert from Protobuf
to other media types such as JSON
.
You can check the schemas that exist under the Schemas tab by logging into Infinispan Console at http://localhost:11222
|
By default, Protobuf schemas generated this way will be registered by this extension when the client first connects. However, it might be required to handle the registration manually as a schema may evolve over time when used in production, so you can disable this from occurring by configuring the quarkus.infinispan-client.use-schema-registration
to false
.
To configure the schema manually please use Infinispan Operator for Kubernetes deployments, Infinispan Console, REST API or the Hot Rod Java Client.
問い合わせ
Infinispan クライアントは、上記の ProtoStreamMarshaller
が設定されている限り、インデックス付きと非インデックス付きの両方の問い合せをサポートしています。これにより、ユーザはプロトスキーマのプロパティに基づいて問い合せできます。
Query は、 ProtoStreamMarshaller
の設定時に設定できるproto定義に基づいて構築されます。上記のいずれのシリアライズ方法でも、起動時に自動的にスキーマをサーバに登録し、リモートの Infinispan サーバーに保存されているオブジェクトを問い合せる機能を自動的に得られます。
詳細は Infinispan のドキュメント 問い合せ を参照してください。
Quarkus Infinispanクライアントエクステンションでは、Query DSLまたはIckle Query 言語のいずれかを使用できます。
カウンター
Infinispanにはカウンターという概念もあり、Quarkus Infinispanのクライアントはそれらもサポートしています。
The Quarkus Infinispan client extension allows for Dependency Injection of the CounterManager
directly. All you need to do is annotate your field, constructor or method, and you get it with no fuss. You can then use counters as you would normally.
@Inject
CounterManager counterManager;
詳細は Infinispan のドキュメント クラスタカウンタ を参照してください。
ニアキャッシング
ニア・キャッシングは既定では無効になっていますが、プロファイル構成プロパティ quarkus.infinispan-client.near-cache-max-entries
を 0 より大きい値に設定することで有効にできます。 また、正規表現を構成して、quarkus.infinispan-client.near-cache-name-pattern
属性を通じたキャッシュの一部のみニア・キャッシングを適用できます。
暗号化
この時点での暗号化には、作業を開始するための追加のステップが必要です。
最初のステップは、 hotrod-client.properties
ファイルがトラストストアおよび/またはキーストアを指すように設定することです。これについては、 ここで さらに詳しく説明します。
The Infinispan Client extension enables SSL/TLS by default. You can read more about this at Using SSL With Native Executables.
追加機能
The Infinispan Client has additional features that were not mentioned here. This means this feature was not tested in a Quarkus environment, and they may or may not work. Please let us know if you need these added!
Dev Services for Infinispan
When you use the infinispan-client extension in dev mode or in test, Quarkus automatically starts an Infinispan server and configure your application.
Enabling / Disabling Dev Services for Infinispan
Dev Services for Infinispan is automatically enabled unless:
-
quarkus.infinispan-client.devservices.enabled
is set tofalse
-
the
quarkus.infinispan-client.server-list
is configured
Dev Services for Infinispan relies on Docker to start the broker. If your environment does not support Docker, you will need to start the broker manually, or connect to an already running broker. You can configure the broker address using quarkus.infinispan-client.server-list
.
共有サーバー
Quarkus will share the Infinispan broker if you have multiple applications running in dev mode. Dev Services for Infinispan implements a service discovery mechanism for your multiple Quarkus applications running in dev mode to share a single broker.
Dev Services for Infinispan starts the container with the quarkus-dev-service-infinispan label which is used to identify the container.
|
If you need multiple (shared) Infinispan server, you can configure the quarkus.infinispan-client.devservices.service-name
attribute and indicate the server name. It looks for a container with the same value, or starts a new one if none can be found. The default service name is infinispan
.
Sharing is enabled by default in dev mode, but disabled in test mode. You can disable the sharing with quarkus.infinispan-client.devservices.shared=false
.
ポートの設定
By default, Dev Services for Infinispan picks a random port and configures the application. You can set the port by configuring the quarkus.infinispan-client.devservices.port
property.
Testing helpers
To start an Infinispan Server for your unit tests, Quarkus provides one QuarkusTestResourceLifecycleManager
that relies on Infinispan Server Test Container.
-
io.quarkus.test.infinispan.client.InfinispanTestResource
will start a single instance on port 11222 with user 'admin' and password 'password'.
To use them, you need to add the io.quarkus:quarkus-test-infinispan-client
dependency to your pom.xml.
For more information about the usage of a QuarkusTestResourceLifecycleManager
please read Quarkus test resource.
設定リファレンス
ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能
タイプ |
デフォルト |
|
---|---|---|
If DevServices has been explicitly enabled or disabled. DevServices is generally enabled by default, unless there is an existing configuration present. When DevServices is enabled Quarkus will attempt to automatically configure and start a database when running in Dev or Test mode and when Docker is running. Environment variable: |
boolean |
|
Optional fixed port the dev service will listen to. If not defined, the port will be chosen randomly. Environment variable: |
int |
|
Indicates if the Infinispan server managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. If a matching container is found, it is used, and so a second one is not started. Otherwise, Dev Services for Infinispan starts a new container.
The discovery uses the Environment variable: |
boolean |
|
The value of the Environment variable: |
string |
|
List of the artifacts to automatically download and add to the Infinispan server libraries. For example a Maven coordinate (org.postgresql:postgresql:42.3.1) or a dependency location url. If an invalid value is passed, the Infinispan server will throw an error when trying to start. Environment variable: |
list of string |
|
Whether a health check is published in case the smallrye-health extension is present. Environment variable: |
boolean |
|
Sets the bounded entry count for near cache. If this value is 0 or less near cache is disabled. Environment variable: |
int |
|
Sets the host name/port to connect to. Each one is separated by a semicolon (eg. host1:11222;host2:11222). Environment variable: |
string |
|
Enables or disables Protobuf generated schemas upload to the server. Set it to 'false' when you need to handle the lifecycle of the Protobuf Schemas on Server side yourself. Default is 'true'. Environment variable: |
boolean |
|
Sets client intelligence used by authentication Available values: * Environment variable: |
string |
|
Enables or disables authentication. Set it to false when connecting to an Infinispan Server without authentication. deployments. Default is 'true'. Environment variable: |
boolean |
|
Sets username used by authentication. Environment variable: |
string |
|
Sets password used by authentication Environment variable: |
string |
|
Sets realm used by authentication Environment variable: |
string |
|
Sets server name used by authentication Environment variable: |
string |
|
Sets client subject, necessary for those SASL mechanisms which require it to access client credentials. Environment variable: |
string |
|
Specifies a Environment variable: |
string |
|
Sets SASL mechanism used by authentication. Available values: * Environment variable: |
string |
|
Specifies the filename of a truststore to use to create the Environment variable: |
string |
|
Specifies the password needed to open the truststore You also need to specify a trustStore. Setting this property implicitly enables SSL/TLS. Environment variable: |
string |
|
Specifies the type of the truststore, such as JKS or JCEKS. Defaults to JKS if trustStore is enabled. Environment variable: |
string |