Hot Rod Java クライアントガイド

Red Hat Data Grid 8.1

Hot Rod Java クライアントの設定および使用

Red Hat Customer Content Services

概要

Hot Rod Java クライアントは、Data Grid クラスターへの高性能リモートアクセスを提供します。

Red Hat Data Grid

Data Grid は、高性能の分散型インメモリーデータストアです。

スキーマレスデータ構造
さまざまなオブジェクトをキーと値のペアとして格納する柔軟性があります。
グリッドベースのデータストレージ
クラスター間でデータを分散および複製するように設計されています。
エラスティックスケーリング
サービスを中断することなく、ノードの数を動的に調整して要件を満たします。
データの相互運用性
さまざまなエンドポイントからグリッド内のデータを保存、取得、およびクエリーします。

Data Grid のドキュメント

Data Grid のドキュメントは、Red Hat カスタマーポータルで入手できます。

Data Grid のダウンロード

Red Hat カスタマーポータルで Data Grid Software Downloads にアクセスします。

注記

Data Grid ソフトウェアにアクセスしてダウンロードするには、Red Hat アカウントが必要です。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。まずは、マスター (master)、スレーブ (slave)、ブラックリスト (blacklist)、ホワイトリスト (whitelist) の 4 つの用語の置き換えから始めます。この取り組みは膨大な作業を要するため、今後の複数のリリースで段階的に用語の置き換えを実施して参ります。詳細は、Red Hat CTO である Chris Wright のメッセージ をご覧ください。

第1章 Hot Rod Java クライアント

Hot Rod Java クライアント API を介してリモートで Data Grid にアクセスします。

1.1. Hot Rod プロトコル

Hot Rod は、Data Grid が次の機能を備えた高性能のクライアントサーバー相互作用を提供するバイナリー TCP プロトコルです。

  • 負荷分散Hot Rod クライアントは、さまざまな戦略を使用して、Data Grid クラスター間でリクエストを送信できます。
  • フェイルオーバーHot Rod クライアントは、Data Grid クラスタートポロジーの変更を監視し、使用可能なノードに自動的に切り替えることができます。
  • 効率的なデータの場所。Hot Rod クライアントは、主要な所有者を見つけてそれらのノードに直接要求を行うことができるため、待ち時間が短縮されます。

1.2. Data Grid Maven リポジトリーの設定

Data Grid Java ディストリビューションは Maven から入手できます。

顧客ポータルから Data Grid Maven リポジトリーをダウンロードするか、パブリック Red Hat Enterprise Maven リポジトリーから Data Grid 依存関係をプルできます。

1.2.1. Data Grid Maven リポジトリーのダウンロード

パブリック Red Hat Enterprise Maven リポジトリーを使用しない場合は、ローカルファイルシステム、Apache HTTP サーバー、または Maven リポジトリーマネージャーに Data Grid Maven リポジトリーをダウンロードし、インストールします。

手順

  1. Red Hat カスタマーポータルにログインします。
  2. Software Downloads for Data Grid に移動します。
  3. Red Hat Data Grid 8.1 Maven リポジトリーをダウンロードします。
  4. アーカイブされた Maven リポジトリーをローカルファイルシステムにデプロイメントします。
  5. README.md ファイルを開き、適切なインストール手順に従います。

1.2.2. Red Hat Maven リポジトリーの追加

Red Hat GA リポジトリーを Maven ビルド環境に組み込み、Data Grid アーティファクトおよび依存関係を取得します。

手順

  • Red Hat GA リポジトリーを Maven 設定ファイル (通常は ~/.m2/settings.xml) に追加するか、プロジェクトの pom.xml ファイルに直接追加します。

    <repositories>
      <repository>
        <id>redhat-ga-repository</id>
        <name>Red Hat GA Repository</name>
        <url>https://maven.repository.redhat.com/ga/</url>
      </repository>
    </repositories>
    <pluginRepositories>
      <pluginRepository>
        <id>redhat-ga-repository</id>
        <name>Red Hat GA Repository</name>
        <url>https://maven.repository.redhat.com/ga/</url>
      </pluginRepository>
    </pluginRepositories>

1.2.3. Data Grid POM の設定

Maven は、プロジェクトオブジェクトモデル (POM) ファイルと呼ばれる設定ファイルを使用して、プロジェクトを定義し、ビルドを管理します。POM ファイルは XML 形式であり、モジュールとコンポーネントの依存関係、ビルドの順序、および結果となるプロジェクトのパッケージ化と出力のターゲットを記述します。

手順

  1. プロジェクト pom.xml を開いて編集します。
  2. 正しい Data Grid バージョンで version.infinispan プロパティーを定義します。
  3. dependencyManagement セクションに infinispan-bom を含めます。

    BOM(Bill of Materials) は、依存関係バージョンを制御します。これにより、バージョンの競合が回避され、プロジェクトに依存関係として追加する Data Grid アーティファクトごとにバージョンを設定する必要がなくなります。

  4. pom.xml を保存して閉じます。

以下の例は、Data Grid のバージョンと BOM を示しています。

<properties>
  <version.infinispan>11.0.9.Final-redhat-00001</version.infinispan>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.infinispan</groupId>
      <artifactId>infinispan-bom</artifactId>
      <version>${version.infinispan}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

次のステップ

必要に応じて、Data Grid アーティファクトを依存関係として pom.xml に追加します。

1.3. Hot Rod Java クライアントの取得

Hot Rod Java クライアントをプロジェクトに追加します。

前提条件

Hot Rod Java クライアントが Java 8 または Java 11 を使用できる。

手順

  • 次のように、pom.xml の依存関係として infinispan-client-hotrod アーティファクトを追加します。
<dependency>
  <groupId>org.infinispan</groupId>
  <artifactId>infinispan-client-hotrod</artifactId>
</dependency>

第2章 Hot Rod Java クライアントの設定

2.1. プログラムによる Hot Rod Java クライアントの設定

ConfigurationBuilder クラスを使用して、RemoteCacheManager に渡すことができるイミュータブルな設定オブジェクトを生成します。

たとえば、以下のように Java Fluent API でクライアントインスタンスを作成します。

org.infinispan.client.hotrod.configuration.ConfigurationBuilder cb
      = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
cb.marshaller(new org.infinispan.commons.marshall.ProtoStreamMarshaller())
  .statistics()
      .enable()
      .jmxDomain("org.example")
  .addServer()
      .host("127.0.0.1")
      .port(11222);
RemoteCacheManager rmc = new RemoteCacheManager(cb.build());

2.2. Hot Rod Java クライアントプロパティーファイルの設定

クライアントが設定を RemoteCacheManager に渡すように、hotrod-client.properties をクラスパスに追加します。

例: hotrod-client.properties ファイル

# Hot Rod client configuration
infinispan.client.hotrod.server_list = 127.0.0.1:11222
infinispan.client.hotrod.marshaller = org.infinispan.commons.marshall.ProtoStreamMarshaller
infinispan.client.hotrod.async_executor_factory = org.infinispan.client.hotrod.impl.async.DefaultAsyncExecutorFactory
infinispan.client.hotrod.default_executor_factory.pool_size = 1
infinispan.client.hotrod.hash_function_impl.2 = org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashV2
infinispan.client.hotrod.tcp_no_delay = true
infinispan.client.hotrod.tcp_keep_alive = false
infinispan.client.hotrod.request_balancing_strategy = org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy
infinispan.client.hotrod.key_size_estimate = 64
infinispan.client.hotrod.value_size_estimate = 512
infinispan.client.hotrod.force_return_values = false

## Connection pooling configuration
maxActive = -1
maxIdle = -1
whenExhaustedAction = 1
minEvictableIdleTimeMillis=300000
minIdle = 1

クラスパス以外の場所に hotrod-client.properties を使用するには、以下を行います。

ConfigurationBuilder b = new ConfigurationBuilder();
Properties p = new Properties();
try(Reader r = new FileReader("/path/to/hotrod-client.properties")) {
   p.load(r);
   b.withProperties(p);
}
RemoteCacheManager rcm = new RemoteCacheManager(b.build());

2.3. クライアントのインテリジェンス

Hot Rod クライアントのインテリジェンスとは、リクエストを効率的にルーティングするために Data Grid サーバーを見つけるメカニズムを指します。

BASIC インテリジェンス

クライアントは、Data Grid クラスターまたはキーハッシュ値に関する情報を保存しません。

トポロジー対応

クライアントは、Data Grid クラスターに関する情報を受信し、保存します。クライアントは、サーバーがクラスターに参加またはクラスターから離脱するたびに変更するクラスタートポロジーの内部マッピングを維持します。

クラスタートポロジーを受信するには、クライアントには、起動時に少なくとも 1 つの Hot Rod サーバーのアドレス(IP:HOST)が必要です。クライアントがサーバーに接続すると、Data Grid はトポロジーをクライアントに送信します。サーバーがクラスターに参加またはクラスターから離脱すると、Data Grid は更新されたトポロジーをクライアントに送信します。

ディストリビューション対応

クライアントはトポロジーに対応し、キーの一貫したハッシュ値を保存します。

たとえば、put (k,v) 操作を取ります。クライアントはキーのハッシュ値を計算して、データが存在する正確なサーバーを見つけられるようにします。その後、クライアントは所有者に直接接続して操作をディスパッチできます。

ディストリビューション対応インテリジェンスの利点は、Data Grid サーバーがキーハッシュに基づいて値を検索する必要がないことです。これは、サーバー側で使用するリソースが少なくなることです。もう 1 つの利点は、サーバーが追加のネットワークラウンドトリップをスキップするため、クライアント要求により迅速に応答することです。

2.3.1. バランシングの要求

topology-aware インテリジェンスを使用するクライアントは、すべてのリクエストに対してリクエストバランシングを使用します。デフォルトのバランシングストラテジーはラウンドロビンであるため、トポロジー対応のクライアントは常にラウンドロビン順でサーバーにリクエストを送信します。

たとえば、s1s2s3 は Data Grid クラスターのサーバーです。クライアントは以下のようにリクエストバランシングを実行します。

CacheContainer cacheContainer = new RemoteCacheManager();
Cache<String, String> cache = cacheContainer.getCache();

//client sends put request to s1
cache.put("key1", "aValue");
//client sends put request to s2
cache.put("key2", "aValue");
//client sends get request to s3
String value = cache.get("key1");
//client dispatches to s1 again
cache.remove("key2");
//and so on...

分散対応インテリジェンスを使用するクライアントは、失敗したリクエストにのみ要求の分散を使用します。リクエストが失敗すると、分散対応のクライアントは次に利用可能なサーバーでリクエストを再試行します。

カスタムバランシングポリシー

FailoverRequestBalancingStrategy を実装し、以下のプロパティーを使用して hotrod-client.properties 設定でクラスを指定できます。

infinispan.client.hotrod.request_balancing_strategy

2.3.2. クライアントフェイルオーバー

Hot Rod クライアントは、Data Grid クラスタートポロジーが変更されたときに自動的にフェイルオーバーできます。たとえば、トポロジー対応の Hot Rod クライアントは、1 つ以上の Data Grid サーバーに障害が発生したことを検出できます。

クラスター化された Data Grid サーバー間のフェイルオーバーに加えて、HotRod クライアントは Data Grid クラスター間でフェイルオーバーをすることができます。

たとえば、ニューヨーク (NYC) で実行している Data Grid クラスターと、ロンドン (LON) で実行している別のクラスターがあるとします。NYCに要求を送信するクライアントは、使用可能なノードがないことを検出したため、LONのクラスターに切り替えます。その後、クライアントは、手動でクラスターを切り替えるか、フェイルオーバーが再度発生するまで、LONへの接続を維持します。

フェイルオーバーを伴うトランザクションキャッシュ

putIfAbsent()replace()remove() などの条件付きオペレーションには、厳密なメソッドの戻り保証があります。同様に、一部のオペレーションでは、以前の値を返さないといけない場合があります。

Hot Rod クライアントはフェイルオーバーが可能ですが、トランザクションキャッシュを使用して、操作が部分的に完了せず、異なるノードに競合するエントリーが残らないようにする必要があります。

2.4. Hot Rod クライアントの認証メカニズムの設定

Data Grid サーバーは、さまざまなメカニズムを使用して Hot Rod クライアント接続を認証します。

手順

  • SecurityConfigurationBuilder クラスの saslMechanism() メソッドで Data Grid サーバーが使用する認証メカニズムを指定します。

SCRAM

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .username("myuser")
         .password("qwer1234!");
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

DIGEST

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .saslMechanism("DIGEST-MD5")
         .username("myuser")
         .password("qwer1234!");
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

PLAIN

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .saslMechanism("PLAIN")
         .username("myuser")
         .password("qwer1234!");
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

OAUTHBEARER

String token = "..."; // Obtain the token from your OAuth2 provider
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .saslMechanism("OAUTHBEARER")
         .token(token);
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

TokenCallbackHandler での OAUTHBEARER 認証

以下の例のように、TokenCallbackHandler でクライアントを設定し、OAuth2 トークンが期限切れになる前に更新できます。

String token = "..."; // Obtain the token from your OAuth2 provider
TokenCallbackHandler tokenHandler = new TokenCallbackHandler(token);
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .saslMechanism("OAUTHBEARER")
         .callbackHandler(tokenHandler);
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");
// Refresh the token
tokenHandler.setToken("newToken");

EXTERNAL

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .ssl()
         // TrustStore stores trusted CA certificates for the server.
         .trustStoreFileName("/path/to/truststore")
         .trustStorePassword("truststorepassword".toCharArray())
         // KeyStore stores valid client certificates.
         .keyStoreFileName("/path/to/keystore")
         .keyStorePassword("keystorepassword".toCharArray())
      .authentication()
         .saslMechanism("EXTERNAL");
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

GSSAPI

LoginContext lc = new LoginContext("GssExample", new BasicCallbackHandler("krb_user", "krb_password".toCharArray()));
lc.login();
Subject clientSubject = lc.getSubject();

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .enable()
         .saslMechanism("GSSAPI")
         .clientSubject(clientSubject)
         .callbackHandler(new BasicCallbackHandler());
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache = remoteCacheManager.getCache("secured");

上記の設定では、BasicCallbackHandler を使用してクライアントサブジェクトを取得し、認証を処理します。ただし、これは実際には異なるコールバックを呼び出します。

  • NameCallback および PasswordCallback は、クライアントサブジェクトを構築します。
  • AuthorizeCallback は、SASL 認証中に呼び出されます。

カスタム CallbackHandler

Hot Rod クライアントは、SASL メカニズムに認証情報を渡すためにデフォルトの CallbackHandler を設定します。カスタムの CallbackHandler を提供する必要がある場合があります。

注記

CallbackHandler は、使用する認証メカニズムに固有のコールバックを処理する必要があります。ただし、考えられる各コールバックタイプの例を提供することは、このドキュメントの範囲を超えています。

public class MyCallbackHandler implements CallbackHandler {
   final private String username;
   final private char[] password;
   final private String realm;

   public MyCallbackHandler(String username, String realm, char[] password) {
      this.username = username;
      this.password = password;
      this.realm = realm;
   }

   @Override
   public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
      for (Callback callback : callbacks) {
         if (callback instanceof NameCallback) {
            NameCallback nameCallback = (NameCallback) callback;
            nameCallback.setName(username);
         } else if (callback instanceof PasswordCallback) {
            PasswordCallback passwordCallback = (PasswordCallback) callback;
            passwordCallback.setPassword(password);
         } else if (callback instanceof AuthorizeCallback) {
            AuthorizeCallback authorizeCallback = (AuthorizeCallback) callback;
            authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals(
                  authorizeCallback.getAuthorizationID()));
         } else if (callback instanceof RealmCallback) {
            RealmCallback realmCallback = (RealmCallback) callback;
            realmCallback.setText(realm);
         } else {
            throw new UnsupportedCallbackException(callback);
         }
      }
   }
}

   ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .authentication()
         .enable()
         .serverName("myhotrodserver")
         .saslMechanism("DIGEST-MD5")
         .callbackHandler(new MyCallbackHandler("myuser","default","qwer1234!".toCharArray()));
remoteCacheManager=new RemoteCacheManager(clientBuilder.build());
RemoteCache<String, String> cache=remoteCacheManager.getCache("secured");

2.4.1. Hot Rod エンドポイント認証メカニズム

Data Grid は、Hot Rod コネクターを使用して以下の SASL 認証メカニズムをサポートします。

認証メカニズム説明関連する詳細

PLAIN

プレーンテキスト形式の認証情報を使用します。PLAIN 認証は、暗号化された接続でのみ使用する必要があります。

Basic HTTP メカニズムに似ています。

DIGEST-*

ハッシュアルゴリズムとナンス値を使用します。ホットロッドコネクターは、強度の順に、DIGEST-MD5DIGEST-SHADIGEST-SHA-256DIGEST-SHA-384、および DIGEST-SHA-512 ハッシュアルゴリズムをサポートします。

Digest HTTP メカニズムに似ています。

SCRAM-*

ハッシュアルゴリズムとナンス値に加えてソルト値を使用します。ホットロッドコネクターは、SCRAM-SHASCRAM-SHA-256SCRAM-SHA-384、および SCRAM-SHA-512 ハッシュアルゴリズムを強度順にサポートします。

Digest HTTP メカニズムに似ています。

GSSAPI

Kerberos チケットを使用し、Kerberos ドメインコントローラーが必要です。対応する Kerberos サーバー ID をレルム設定に追加する必要があります。ほとんどの場合、ユーザーメンバーシップ情報を提供するために ldap-realm も指定します。

SPNEGO HTTP メカニズムに似ています。

GS2-KRB5

Kerberos チケットを使用し、Kerberos ドメインコントローラーが必要です。対応する Kerberos サーバー ID をレルム設定に追加する必要があります。ほとんどの場合、ユーザーメンバーシップ情報を提供するために ldap-realm も指定します。

SPNEGO HTTP メカニズムに似ています。

EXTERNAL

クライアント証明書を使用します。

CLIENT_CERTHTTP メカニズムに似ています。

OAUTHBEARER

OAuth トークンを使用し、token-realm 設定が必要です。

BEARER_TOKEN HTTP メカニズムに似ています。

2.4.2. GSSAPI ログインコンテキストの作成

GSSAPI メカニズムを使用するには、LoginContextを作成して、Hot Rod クライアント Ticket Granting Ticket (TGT) を取得できるようにする必要があります。

手順

  1. ログイン設定ファイルでログインモジュールを定義します。

    gss.conf

    GssExample {
        com.sun.security.auth.module.Krb5LoginModule required client=TRUE;
    };

    IBM JDK の場合:

    gss-ibm.conf

    GssExample {
        com.ibm.security.auth.module.Krb5LoginModule required client=TRUE;
    };

  2. 次のシステムプロパティーを設定します。

    java.security.auth.login.config=gss.conf
    
    java.security.krb5.conf=/etc/krb5.conf
    注記

    krb5.conf は、KDC の場所を提供します。kinitコマンドを使用して、Kerberos で認証し、krb5.conf を確認します。

2.5. Hot Rod クライアントの暗号化の設定

SSL/TLS 暗号化を使用する Data Grid サーバーは、証明書で Hot Rod クライアントを提示します。これにより、信頼を確立し、セキュアな接続をネゴシエートできます。

サーバー発行の証明書を確認するには、Hot Rod クライアントには TLS 証明書チェーンの一部が必要です。たとえば、次のイメージは、HotRodServer という名前のサーバーの証明書を発行した CA という名前の認証局 (CA) を示しています。

図2.1 証明書チェーン

証明書チェーン

手順

  1. サーバー証明書チェーンの一部で Java キーストアを作成します。ほとんどの場合、CA の公開証明書を使用する必要があります。
  2. SslConfigurationBuilder クラスを使用して、キーストアをクライアント設定で TrustStore として指定します。
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
      .host("127.0.0.1")
      .port(11222)
   .security()
      .ssl()
         // Server SNI hostname.
         .sniHostName("myservername")
         // Server certificate keystore.
         .trustStoreFileName("/path/to/truststore")
         .trustStorePassword("truststorepassword".toCharArray())
         // Client certificate keystore.
         .keyStoreFileName("/path/to/client/keystore")
         .keyStorePassword("keystorepassword".toCharArray());
RemoteCache<String, String> cache=remoteCacheManager.getCache("secured");
ヒント

PEM 形式の証明書を含むパスを指定し、Hot Rod クライアントはトラストストアを自動的に生成します。

.trustStorePath("/path/to/certificate") を使用します。

2.6. Hot Rod クライアント統計の監視

リモートおよびニアキャッシュのヒットとミス、および接続プールの使用状況を含む Hot Rod クライアント統計を有効にします。

手順

  • StatisticsConfigurationBuilder クラスを使用して、Hot Rod クライアント統計を有効にして設定します。
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .statistics()
    //Enable client statistics.
    .enable()
   //Register JMX MBeans for RemoteCacheManager and each RemoteCache.
   .jmxEnable()
    //Set JMX domain name to which MBeans are exposed.
    .jmxDomain("org.example")
   .addServer()
    .host("127.0.0.1")
    .port(11222);
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());

2.7. クライアント設定での Data Grid クラスターの定義

Hot Rod クライアント設定で Data Grid クラスターの場所を指定します。

手順

  • ClusterConfigurationBuilder クラスを使用して、少なくとも 1 つの Data Grid クラスター名、ホスト名、およびポートを指定します。

    ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
    clientBuilder
       .addCluster("siteA")
         .addClusterNode("hostA1", 11222)
         .addClusterNode("hostA2", 11222)
       .addCluster("siteB")
         .addClusterNodes("hostB1:11222; hostB2:11222");
    remoteCacheManager = new RemoteCacheManager(clientBuilder.build());

デフォルトのクラスター

クラスターを Hot Rod クライアント設定に追加する場合、hostname1:port; hostname2:port の形式で Data Grid サーバーの一覧を定義できます。次に、Data Grid はサーバーリストをデフォルトのクラスター設定として使用します。

ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServers("hostA1:11222; hostA2:11222")
   .addCluster("siteB")
     .addClusterNodes("hostB1:11222; hostB2:11223");
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());

2.7.1. Data Grid クラスターの手動切り替え

Data Grid クラスター間で Hot Rod Java クライアント接続を手動で切り替えます。

手順

  • RemoteCacheManager クラスで次のいずれかのメソッドを呼び出します。

    switchToCluster(clusterName) は、クライアント設定で定義された特定のクラスターに切り替えます。

    switchToDefaultCluster() は、Data Grid サーバーのリストとして定義されているクライアント設定のデフォルトクラスターに切り替えます。

2.8. Hot Rod クライアントを使用したキャッシュの作成

RemoteCacheManager API を使用して、プログラムにより Data Grid Server 上にキャッシュを作成します。

注記

次の手順は、Hot Rod Java クライアントを使用した、プログラムによるキャッシュの作成を示しています。ただし、Hot Rod クライアントは、JavaScript や C++ などのさまざまな言語で利用できます。

前提条件

  • ユーザーを作成し、少なくとも 1 つの Data Grid サーバーインスタンスを開始している。
  • Hot Rod Java クライアントを入手している。

手順

  1. ConfigurationBuilder クラスを使用してクライアントを設定します。

    import org.infinispan.client.hotrod.RemoteCacheManager;
    import org.infinispan.client.hotrod.DefaultTemplate;
    import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
    import org.infinispan.commons.configuration.XMLStringConfiguration;
    ...
    
    ConfigurationBuilder builder = new ConfigurationBuilder();
    builder.addServer()
             .host("127.0.0.1")
             .port(11222)
           .security().authentication()
              .enable()
              .username("username")
              .password("password")
              .realm("default")
              .saslMechanism("DIGEST-MD5");
    
    manager = new RemoteCacheManager(builder.build());
  2. XMLStringConfiguration クラスを使用して、XML 形式でキャッシュ定義を追加します。
  3. getOrCreateCache() メソッドを呼び出して、キャッシュがすでに存在する場合は追加し、存在しない場合は作成します。

    private void createCacheWithXMLConfiguration() {
        String cacheName = "CacheWithXMLConfiguration";
        String xml = String.format("<infinispan>" +
                                      "<cache-container>" +
                                      "<distributed-cache name=\"%s\" mode=\"SYNC\"
                                      statistics=\"true\">" +
                                        "<locking isolation=\"READ_COMMITTED\"/>" +
                                        "<transaction mode=\"NON_XA\"/>" +
                                        "<expiration lifespan=\"60000\" interval=\"20000\"/>" +
                                      "</distributed-cache>" +
                                      "</cache-container>" +
                                    "</infinispan>"
                                    , cacheName);
        manager.administration().getOrCreateCache(cacheName, new XMLStringConfiguration(xml));
        System.out.println("Cache created or already exists.");
    }
  4. 次の例のように、createCache() 呼び出しにより org.infinispan テンプレートを使用してキャッシュを作成します。

    private void createCacheWithTemplate() {
        manager.administration().createCache("myCache", "org.infinispan.DIST_SYNC");
        System.out.println("Cache created.");
    }

次のステップ

実際に動作するコード例をいくつか試すことで、Hot Rod Java クライアントを使用してリモートキャッシュを作成する方法を確認できます。Data Grid Tutorials を参照してください。

2.9. 最初のアクセスでのキャッシュの作成

Hot Rod Java クライアントが存在しないキャッシュにアクセスしようとすると、getCache("$cacheName") 呼び出しに対して null を返します。

このデフォルトの動作を変更し、クライアントが XML 形式のデフォルト設定テンプレートまたは Data Grid キャッシュ定義を使用して、最初のアクセスでキャッシュを自動的に作成できるようにします。

プログラムによる手順

  • 次のように、remoteCache() メソッドを使用して、Hot Rod ConfigurationBuilder クラスでキャッシュごとの設定を作成します。
import org.infinispan.client.hotrod.DefaultTemplate;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
...

ConfigurationBuilder builder = new ConfigurationBuilder();
builder.remoteCache("my-cache") 1
    .templateName(DefaultTemplate.DIST_SYNC)
builder.remoteCache("another-cache") 2
    .configuration("<infinispan><cache-container><distributed-cache name=\"another-cache\"/></cache-container></infinispan>");
builder.remoteCache("my-other-cache") 3
    .configurationURI(URI.create("file:/path/to/configuration.xml"));
1
org.infinispan.DIST_SYNC テンプレートから "my-cache" という名前のキャッシュを作成します。
2
XML 定義から "another-cache" という名前のキャッシュを作成します。
3
XML ファイルから "my-other-cache" という名前のキャッシュを作成します。

Hot Rod クライアントプロパティー

  • infinispan.client.hotrod.cache.<cache-name> プロパティーを hotrod-client.properties ファイルに追加して、次のようにキャッシュごとの設定を作成します。
infinispan.client.hotrod.cache.my-cache.template_name=org.infinispan.DIST_SYNC 1
infinispan.client.hotrod.cache.another-cache.configuration=<infinispan><cache-container><distributed-cache name=\"another-cache\"/></cache-container></infinispan> 2
infinispan.client.hotrod.cache.my-other-cache.configuration_uri=file:/path/to/configuration.xml 3
1
org.infinispan.DIST_SYNC テンプレートから "my-cache" という名前のキャッシュを作成します。
2
XML 定義から "another-cache" という名前のキャッシュを作成します。
3
XML ファイルから "my-other-cache" という名前のキャッシュを作成します。

2.10. キャッシュごとの設定の作成

最初のアクセス時にキャッシュを作成することに加えて、次のような個々のキャッシュの特定要素をリモートで設定できます。

  • 戻り値の強制
  • ニアキャッシュ
  • トランザクションモード

手順

  • 次のように、a-cache という名前のキャッシュの force return values を有効にします。
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
...

ConfigurationBuilder builder = new ConfigurationBuilder();
builder
  .remoteCache("a-cache")
    .forceReturnValues(true);
  • リモートキャッシュ名でワイルドカードグロビングを使用して、文字列 somecaches で始まるすべてのキャッシュの force return values を有効にします。
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
...

ConfigurationBuilder builder = new ConfigurationBuilder();
builder
  .remoteCache("somecaches*")
    .forceReturnValues(true);
注記

宣言型設定を使用しており、キャッシュ名が . の文字を含む場合は、キャッシュ名を角括弧で囲む必要があります (例: infinispan.client.hotrod.cache.[example.MyCache].template=…​)。

2.11. ニアキャッシングの設定

Hot Rod Java クライアントは、最近使用されたデータを格納するローカルキャッシュを保持することができます。これにより、データはクライアントにローカルであるため、get() および getVersioned() 操作のパフォーマンスが大幅に向上します。

Hot Rod Java クライアントでニアキャッシュを有効にすると、get() または getVersioned() 呼び出しにより、エントリーがサーバーから取得される際にニアキャッシュが設定されます。サーバー側でエントリーが更新または削除されると、ニアキャッシュのエントリーが無効になります。キーが無効になった後にリクエストされた場合、クライアントはサーバーからキーを再度取得する必要があります。

ニアキャッシュに含めることができるエントリーの数を設定することもできます。最大に達すると、ニアキャッシュされたエントリーはエビクトされます。

ニアキャッシュに関する考慮事項

ニアキャッシュ読み取りはエントリーの最終アクセス時間を伝播しないため、ニアキャッシュで最大アイドル有効期限を使用しないでください。

  • クラスター化されたキャッシュモードを使用すると、クライアントが異なるサーバーにフェイルオーバーすると、ニアキャッシュが消去されます。
  • ニアキャッシュに格納できるエントリーの最大数を常に設定する必要があります。非有界のニアキャッシュでは、クライアント JVM の境界内にニアキャッシュのサイズを保持する必要があります。
  • ニアキャッシュの無効化メッセージにより書き込み操作のパフォーマンスが低下します。

手順

  1. 必要なキャッシュのクライアント設定で、ニアキャッシュモードを INVALIDATED に設定します。
  2. エントリーの最大数を指定して、ニアキャッシュのサイズを定義します。
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.infinispan.client.hotrod.configuration.NearCacheMode;
...

// Configure different near cache settings for specific caches
ConfigurationBuilder builder = new ConfigurationBuilder();
builder
  .remoteCache("bounded")
    .nearCacheMode(NearCacheMode.INVALIDATED)
    .nearCacheMaxEntries(100);
  .remoteCache("unbounded").nearCache()
    .nearCacheMode(NearCacheMode.INVALIDATED)
    .nearCacheMaxEntries(-1);
注記

キャッシュごとに、常にニアキャッシュを設定する必要があります。Data Grid はグローバルニアキャッシュ設定プロパティーを提供しますが、使用しないでください。

2.12. 戻り値の強制

不必要にデータを送信しないようにするために、リモートキャッシュでの書き込み操作は、以前の値ではなく null を返します。

たとえば、以下のメソッド呼び出しでは、キーに対する以前の値は返されません。

V remove(Object key);
V put(K key, V value);

FORCE_RETURN_VALUE フラグを使用してこのデフォルトの動作を変更すると、呼び出しで以前の値が返されるようになります。

手順

  • null ではなく以前の値を取得するには、次の例のように FORCE_RETURN_VALUE フラグを使用します。
cache.put("aKey", "initialValue");
assert null == cache.put("aKey", "aValue");
assert "aValue".equals(cache.withFlags(Flag.FORCE_RETURN_VALUE).put("aKey",
   "newValue"));

2.13. 接続プールの設定

Hot Rod Java クライアントは、Data Grid サーバーへの永続的な接続のプールを保持して、要求ごとに TCP 接続を作成するのではなく、TCP 接続を再利用します。

クライアントは非同期スレッドを使用して、接続プールを繰り返し処理し、Data Grid サーバーに ping を送信することで、接続の有効性を確認します。これにより、アプリケーション要求ではなく、プール内でアイドル状態である間に破損した接続を見つけることで、パフォーマンスが向上します。

手順

  • ConnectionPoolConfigurationBuilder クラスを使用して Hot Rod クライアント接続プールを設定します。
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
   .addServer()
    .host("127.0.0.1")
    .port(11222)
    //Configure client connection pools.
    .connectionPool()
    //Set the maximum number of active connections per server.
    .maxActive(10)
    //Set the minimum number of idle connections
    //that must be available per server.
    .minIdle(20);
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());

2.14. Hot Rod Java クライアントマーシャリング

Hot Rod は、Java オブジェクトをバイナリー形式に変換する必要があるバイナリー TCP プロトコルです。これにより、ネットワーク経由で転送したり、ディスクに保存したりできます。

デフォルトでは、Data Grid は ProtoStream API を使用して、言語に依存しない下位互換性のある形式で、Java オブジェクトをプロトコルバッファー (Protobuf) にエンコードおよびデコードします。ただし、カスタムマーシャラーを実装して使用することもできます。

2.14.1. SerializationContextInitializer 実装の設定

ProtoStream SerializationContextInitializer インターフェイスの実装を Hot Rod クライアント設定に追加して、Data Grid がカスタム Java オブジェクトをマーシャリングできるようにします。

手順

  • 以下のように SerializationContextInitializer 実装を Hot Rod クライアント設定に追加します。

hotrod-client.properties

infinispan.client.hotrod.context-initializers=org.infinispan.example.LibraryInitializerImpl,org.infinispan.example.AnotherExampleSciImpl

プログラムによる設定

ConfigurationBuilder builder = new ConfigurationBuilder();
builder
      .addServer()
      .host("127.0.0.1")
      .port(11222)
      .addContextInitializers(new LibraryInitializerImpl(), new AnotherExampleSciImpl());
RemoteCacheManager rcm = new RemoteCacheManager(builder.build());

2.14.2. カスタムマーシャラーの設定

カスタムマーシャラーを使用するように Hot Rod クライアントを設定します。

手順

  1. org.infinispan.commons.marshall.Marshaller インターフェイスを実装します。
  2. Hot Rod クライアント設定でクラスの完全修飾名を指定します。
  3. Java クラスを Data Grid デシリアライズホワイトリストに追加します。

    以下の例では、Person または Employee が含まれる完全修飾名を持つクラスのみが許可されます。

    ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
    clientBuilder.marshaller("org.infinispan.example.marshall.CustomMarshaller")
      .addJavaSerialWhiteList(".*Person.*", ".*Employee.*");
      ...

2.15. Hot Rod クライアントデータ形式の設定

デフォルトでは、Hot Rod クライアント操作は、キーと値の両方に Data Grid サーバーから読み書きする際に、設定されたマーシャラーを使用します。

ただし、DataFormat API を使用すると、すべての操作がカスタムデータ形式で実行されるようにリモートキャッシュを切り離すことができます。

キーと値の異なるマーシャラーの使用

キーと値のマーシャラーはランタイム時に上書きできます。たとえば、Hot Rod クライアントのすべてのシリアル化をバイパスし、サーバーに保存されているため byte[] を読み取るには、以下を実行します。

// Existing RemoteCache instance
RemoteCache<String, Pojo> remoteCache = ...

// IdentityMarshaller is a no-op marshaller
DataFormat rawKeyAndValues =
DataFormat.builder()
          .keyMarshaller(IdentityMarshaller.INSTANCE)
          .valueMarshaller(IdentityMarshaller.INSTANCE)
          .build();

// Creates a new instance of RemoteCache with the supplied DataFormat
RemoteCache<byte[], byte[]> rawResultsCache =
remoteCache.withDataFormat(rawKeyAndValues);
重要

keyMarshaller() および keyType() メソッドでキーに異なるマーシャラーと形式を使用すると、クライアントインテリジェンスルーティングメカニズムに干渉し、Data Grid クラスター内で追加のホップが操作を実行する可能性があります。パフォーマンスが重要な場合は、サーバーによって保存された形式のキーを使用する必要があります。

XML 値を返す

Object xmlValue = remoteCache
      .withDataFormat(DataFormat.builder()
      .valueType(APPLICATION_XML)
      .valueMarshaller(new UTF8StringMarshaller())
      .build())
      .get(key);

上記のコード例は、以下のように XML 値を返します。

<?xml version="1.0" ?><string>Hello!</string>

異なる形式でのデータの読み取り

以下のように、org.infinispan.commons.dataconversion.MediaType で指定された異なる形式でデータを要求および送信します。

// Existing remote cache using ProtostreamMarshaller
RemoteCache<String, Pojo> protobufCache = ...

// Request values returned as JSON
// Use the UTF8StringMarshaller to convert UTF-8 to String
DataFormat jsonString =
DataFormat.builder()
          .valueType(MediaType.APPLICATION_JSON)
          .valueMarshaller(new UTF8StringMarshaller())
          .build();
RemoteCache<byte[], byte[]> rawResultsCache =
protobufCache.withDataFormat(jsonString);
// Alternatively, use a custom value marshaller
// that returns `org.codehaus.jackson.JsonNode` objects
DataFormat jsonNode =
DataFormat.builder()
          .valueType(MediaType.APPLICATION_JSON)
          .valueMarshaller(new CustomJacksonMarshaller()
          .build();

RemoteCache<String, JsonNode> jsonNodeCache =
remoteCache.withDataFormat(jsonNode);

上記の例では、Data Grid サーバーでデータ変換が行われます。ストレージ形式への変換をサポートしていない場合、Data Grid は例外を出力します。

第3章 Hot Rod クライアント API

Data Grid Hot Rod クライアント API は、リモートでのキャッシュ作成、データ操作、クラスター化されたキャッシュのトポロジー監視を行うためのインターフェイスを提供します。

3.1. Basic API

以下は、クライアント API を使用して Java Hot Rod クライアントを使用して Data Grid サーバーから情報を保存または取得するためのサンプルコードスニペットです。Data Grid サーバーが localhost:11222 で実行されていることを前提としています。

//API entry point, by default it connects to localhost:11222
CacheContainer cacheContainer = new RemoteCacheManager();

//obtain a handle to the remote default cache
Cache<String, String> cache = cacheContainer.getCache();

//now add something to the cache and make sure it is there
cache.put("car", "ferrari");
assert cache.get("car").equals("ferrari");

//remove the data
cache.remove("car");
assert !cache.containsKey("car") : "Value must have been removed!";

クライアント API はローカル API をマッピングします。RemoteCacheManagerDefaultCacheManager に対応します(どちらも CacheContainer を実装します)。この共通 API により、ローカル呼び出しから Hot Rod を介したリモート呼び出しへの移行が容易になります。必要なのは、DefaultCacheManagerRemoteCacheManager を切り替えることだけです。これは、両方が継承する共通の CacheContainer インターフェイスによってさらに簡素化されます。

3.2. RemoteCache API

コレクションメソッド keySetentrySet、および values はリモートキャッシュによってサポートされます。つまり、すべてのメソッドが RemoteCache に戻されるということです。これは、さまざまなキー、エントリー、または値を遅延して取得でき、ユーザーが望まない場合にそれらすべてを一度にクライアントメモリーに保存する必要がないため便利です。

これらのコレクションは、add および addAll はサポートされていませんが、他のすべてのメソッドはサポートされているという Map 仕様に準拠しています。

注記の 1 つとして、Iterator.remove メソッドおよび Set.remove メソッドまたは Collection.remove メソッドには、操作するサーバーに 1 つ以上のラウンドトリップが必要です。RemoteCache Javadoc を参照して、これらのメソッドおよび他のメソッドの詳細を確認できます。

イテレーターの使用

これらのコレクションの iterator メソッドは、以下で説明されている retrieveEntries を内部で使用します。retrieveEntries がバッチサイズの引数を取る場合。これをイテレータに提供する方法はありません。そのため、バッチサイズは、システムプロパティー infinispan.client.hotrod.batch_size で設定するか、または RemoteCacheManager の設定時に ConfigurationBuilder で設定することができます。

また、返される retrieveEntries イテレーターは Closeable です。keySetentrySet、および values からのイテレーターは AutoCloseable バリアントを返します。したがって、これらの Iterator の使用が終了したら、常に閉じる必要があります。

try (CloseableIterator<Map.Entry<K, V>> iterator = remoteCache.entrySet().iterator()) {

      }

バッキングコレクションではなく、ディープコピーが必要な場合

以前のバージョンの RemoteCache では、keySet のディープコピーの取得が許可されました。これは新しいバッキングマップでも可能です。コンテンツを自分でコピーするだけです。また、これまでサポートしていなかった entrySet および values を使用してこれを行うこともできます。

Set<K> keysCopy = remoteCache.keySet().stream().collect(Collectors.toSet());

3.2.1. サポートされていないメソッド

Data Grid の RemoteCache API は、Cache API で利用可能なすべてのメソッドをサポートしておらず、サポート対象外のメソッドが呼び出されると UnsupportedOperationException を出力します。

これらのメソッドのほとんどはリモートキャッシュ (リスナー管理操作など) では意味を持ちません。または、ローカルキャッシュでサポートされていないメソッドにも対応しません (例: containsValue)。

ConcurrentMap から継承された特定のアトミック操作も、RemoteCache API ではサポートされていません。以下に例を示します。

boolean remove(Object key, Object value);
boolean replace(Object key, Object value);
boolean replace(Object key, Object oldValue, Object value);

ただし、RemoteCache は、値オブジェクト全体ではなく、ネットワーク経由でバージョン識別子を送信する、これらのアトミック操作の代替バージョンメソッドを提供します。

3.3. リモート Iterator API

Data Grid は、メモリーリソースが制限されているエントリーを取得するため、またはサーバー側のフィルタリングや変換を行う予定がある場合に、リモートイテレータ API を提供します。

// Retrieve all entries in batches of 1000
int batchSize = 1000;
try (CloseableIterator<Entry<Object, Object>> iterator = remoteCache.retrieveEntries(null, batchSize)) {
     while(iterator.hasNext()) {
        // Do something
     }
}

// Filter by segment
Set<Integer> segments = ...
try (CloseableIterator<Entry<Object, Object>> iterator = remoteCache.retrieveEntries(null, segments, batchSize)) {
     while(iterator.hasNext()) {
        // Do something
     }
}

// Filter by custom filter
try (CloseableIterator<Entry<Object, Object>> iterator = remoteCache.retrieveEntries("myFilterConverterFactory", segments, batchSize)) {
     while(iterator.hasNext()) {
        // Do something
     }
}

3.3.1. Data Grid サーバーへのカスタムフィルターのデプロイ

カスタムフィルターを Data Grid サーバーインスタンスにデプロイします。

手順

  1. KeyValueFilterConverterFactory を拡張するファクトリーを作成します。

    import java.io.Serializable;
    
    import org.infinispan.filter.AbstractKeyValueFilterConverter;
    import org.infinispan.filter.KeyValueFilterConverter;
    import org.infinispan.filter.KeyValueFilterConverterFactory;
    import org.infinispan.filter.NamedFactory;
    import org.infinispan.metadata.Metadata;
    
    //@NamedFactory annotation defines the factory name
    @NamedFactory(name = "myFilterConverterFactory")
    public class MyKeyValueFilterConverterFactory implements KeyValueFilterConverterFactory {
    
       @Override
       public KeyValueFilterConverter<String, SampleEntity1, SampleEntity2> getFilterConverter() {
          return new MyKeyValueFilterConverter();
       }
       // Filter implementation. Should be serializable or externalizable for DIST caches
       static class MyKeyValueFilterConverter extends AbstractKeyValueFilterConverter<String, SampleEntity1, SampleEntity2> implements Serializable {
          @Override
          public SampleEntity2 filterAndConvert(String key, SampleEntity1 entity, Metadata metadata) {
             // returning null will case the entry to be filtered out
             // return SampleEntity2 will convert from the cache type SampleEntity1
          }
    
          @Override
          public MediaType format() {
             // returns the MediaType that data should be presented to this converter.
             // When ommitted, the server will use "application/x-java-object".
             // Returning null will cause the filter/converter to be done in the storage format.
          }
       }
    }
  2. META-INF/services/org.infinispan.filter.KeyValueFilterConverterFactory ファイルが含まれる JAR を作成します。このファイルには、フィルターファクトリークラス実装の完全修飾クラス名を含める必要があります。

    フィルターがカスタムのキー/値クラスを使用する場合は、フィルターがキーや値のインスタンスを正しくアンマーシャリングできるように、それらを JAR ファイルに含める必要があります。

  3. JAR ファイルを Data Grid サーバーのインストールディレクトリーの server/lib ディレクトリーに追加します。

3.4. MetadataValue API

バージョン管理された操作には、MetadataValue インターフェイスを使用します。

次の例は、エントリーの値のバージョンが変更されていない場合にのみ発生する削除操作を示しています。

RemoteCacheManager remoteCacheManager = new RemoteCacheManager();
      RemoteCache<String, String> remoteCache = remoteCacheManager.getCache();

      remoteCache.put("car", "ferrari");
      VersionedValue valueBinary = remoteCache.getWithMetadata("car");

      assert remoteCache.remove("car", valueBinary.getVersion());
      assert !remoteCache.containsKey("car");

3.5. ストリーミング API

Data Grid は、InputStream および OutputStream のインスタンスを返すメソッドを実装する Streaming API を提供するため、Hot Rod クライアントと Data Grid サーバー間で大きなオブジェクトをストリーミングできます。

大きなオブジェクトの次の例を考えてみましょう。

StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
OutputStream os = streamingCache.put("a_large_object");
os.write(...);
os.close();

次のように、ストリーミングを通じてオブジェクトを読み取ることができます。

StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
InputStream is = streamingCache.get("a_large_object");
for(int b = is.read(); b >= 0; b = is.read()) {
   // iterate
}
is.close();
注記

Streaming API は値をマーシャリング しません。つまり、Streaming API と非 Streaming API の両方を同時に使用することはできません。ただし、このケースを処理するためにカスタムマーシャラーを実装することもできます。

RemoteStreamingCache.get(K key) メソッドによって返される InputStreamVersionedMetadata インターフェイスを実装しているため、以下のようにバージョンと有効期限の情報を取得できます。

StreamingRemoteCache<String> streamingCache = remoteCache.streaming();
InputStream is = streamingCache.get("a_large_object");
long version = ((VersionedMetadata) is).getVersion();
for(int b = is.read(); b >= 0; b = is.read()) {
   // iterate
}
is.close();
注記

条件付き書き込みメソッド (putIfAbsent()replace()) は、値がサーバーに完全に送信されてから、実際の条件チェックを実行します。つまり、close() メソッドが OutputStream で呼び出される場合です。

3.6. カウンター API

CounterManager インターフェイスは、カウンターを定義、取得、および削除するエントリーポイントです。

Hot Rod クライアントは、以下の例のように CounterManager インターフェイスを取得できます。

// create or obtain your RemoteCacheManager
RemoteCacheManager manager = ...;

// retrieve the CounterManager
CounterManager counterManager = RemoteCounterManagerFactory.asCounterManager(manager);

3.7. イベントリスナーの作成

Java Hot Rod クライアントは、リスナーを登録して cache-entry レベルのイベントを受信することができます。キャッシュエントリーの作成、変更、および削除されたイベントがサポートされています。

クライアントリスナーの作成は、異なるアノテーションとイベントクラスが使用される点を除き、組み込みリスナーと非常に似ています。受信した各イベントを出力するクライアントリスナーの例を次に示します。

import org.infinispan.client.hotrod.annotation.*;
import org.infinispan.client.hotrod.event.*;

@ClientListener
public class EventPrintListener {

   @ClientCacheEntryCreated
   public void handleCreatedEvent(ClientCacheEntryCreatedEvent e) {
      System.out.println(e);
   }

   @ClientCacheEntryModified
   public void handleModifiedEvent(ClientCacheEntryModifiedEvent e) {
      System.out.println(e);
   }

   @ClientCacheEntryRemoved
   public void handleRemovedEvent(ClientCacheEntryRemovedEvent e) {
      System.out.println(e);
   }

}

ClientCacheEntryCreatedEvent および ClientCacheEntryModifiedEvent インスタンスは、影響を受けるキーとエントリーのバージョンに関する情報を提供します。このバージョンは、replaceWithVersionremoveWithVersion などのサーバー上で条件付き操作を呼び出すために使用できます。

ClientCacheEntryRemovedEvent イベントは、削除操作が成功した場合にのみ送信されます。つまり、削除オペレーションが呼び出されても、エントリーが見つからないか、エントリーを削除する必要がない場合は、イベントが生成されません。エントリーが削除されていなくても、削除されたイベントに関心のあるユーザーは、このようなイベントを生成するイベントのカスタマイズロジックを開発できます。詳細は、クライアントイベントのカスタマイズ セクションを参照してください。

ClientCacheEntryCreatedEventClientCacheEntryModifiedEvent、および ClientCacheEntryRemovedEvent のすべてのイベントインスタンスも、トポロジーの変更が原因でこれを引き起こした書き込みコマンドを再度実行する場合に true を返す boolean isCommandRetried() メソッドも提供します。これは、このイベントが重複したか、別のイベントが破棄されて置き換えられた記号になります (例: ClientCacheEntryModifiedEvent が ClientCacheEntryCreatedEvent に置き換えます)。

クライアントリスナーの実装を作成したら、サーバーに登録する必要があります。これを行うには、以下を実行します。

RemoteCache<?, ?> cache = ...
cache.addClientListener(new EventPrintListener());

3.7.1. イベントリスナーの削除

クライアントイベントリスナーが必要ない場合は、以下を削除できます。

EventPrintListener listener = ...
cache.removeClientListener(listener);

3.7.2. イベントのフィルタリング

クライアントにイベントが殺到するのを防ぐために、ユーザーはフィルタリング機能を提供して、特定のクライアントリスナーに対し、サーバーによって発生するイベントの数を制限できます。フィルターを有効にするには、フィルターインスタンスを生成するキャッシュイベントフィルターファクトリーを作成する必要があります。

import org.infinispan.notifications.cachelistener.filter.CacheEventFilterFactory;
import org.infinispan.filter.NamedFactory;

@NamedFactory(name = "static-filter")
public static class StaticCacheEventFilterFactory implements CacheEventFilterFactory {

   @Override
   public StaticCacheEventFilter getFilter(Object[] params) {
      return new StaticCacheEventFilter();
   }
}


// Serializable, Externalizable or marshallable with Infinispan Externalizers
// needed when running in a cluster
class StaticCacheEventFilter implements CacheEventFilter<Integer, String>, Serializable {
   @Override
   public boolean accept(Integer key, String oldValue, Metadata oldMetadata,
         String newValue, Metadata newMetadata, EventType eventType) {
      if (key.equals(1)) // static key
         return true;

      return false;
   }
}

上記で定義されたキャッシュイベントフィルターファクトリーインスタンスは、キーが 1 であるものを除くすべてのエントリーを静的にフィルターするインスタンスを作成します。

このキャッシュイベントフィルターファクトリーにリスナーを登録できるようにするには、ファクトリーに一意の名前を付ける必要があり、Hot Rod サーバーに名前とキャッシュイベントフィルターファクトリーインスタンスを接続する必要があります。

  1. フィルターの実装を含む JAR ファイルを作成します。

    キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで useRawData が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。

  2. JAR ファイル内で META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventFilterFactory ファイルを作成し、フィルタークラス実装の完全修飾クラス名を作成します。
  3. JAR ファイルを Data Grid サーバーのインストールディレクトリーの server/lib ディレクトリーに追加します。
  4. ファクトリー名を @ClientListener アノテーションに追加して、クライアントリスナーをこのキャッシュイベントフィルターファクトリーとリンクします。

    @ClientListener(filterFactoryName = "static-filter")
    public class EventPrintListener { ... }
  5. リスナーをサーバーに登録します。

    RemoteCache<?, ?> cache = ...
    cache.addClientListener(new EventPrintListener());

リスナーの登録時に提供されたパラメーターに基づいてフィルタリングする動的フィルターインスタンスを登録することもできます。フィルターは、フィルターファクトリーが受け取ったパラメーターを使用してこのオプションを有効にします。以下に例を示します。

import org.infinispan.notifications.cachelistener.filter.CacheEventFilterFactory;
import org.infinispan.notifications.cachelistener.filter.CacheEventFilter;

class DynamicCacheEventFilterFactory implements CacheEventFilterFactory {
   @Override
   public CacheEventFilter<Integer, String> getFilter(Object[] params) {
      return new DynamicCacheEventFilter(params);
   }
}

// Serializable, Externalizable or marshallable with Infinispan Externalizers
// needed when running in a cluster
class DynamicCacheEventFilter implements CacheEventFilter<Integer, String>, Serializable {
   final Object[] params;

   DynamicCacheEventFilter(Object[] params) {
      this.params = params;
   }

   @Override
   public boolean accept(Integer key, String oldValue, Metadata oldMetadata,
         String newValue, Metadata newMetadata, EventType eventType) {
      if (key.equals(params[0])) // dynamic key
         return true;

      return false;
   }
}

リスナーの登録時に、フィルタリングに必要な動的パラメーターが提供されます。

RemoteCache<?, ?> cache = ...
cache.addClientListener(new EventPrintListener(), new Object[]{1}, null);
警告

フィルターインスタンスは、クラスターにデプロイされるときにマーシャル可能である必要があります。これにより、リスナーの登録先の別のノードで生成された場合でも、イベントが生成される際にフィルターが適切に行われるようにします。それらをマーシャリング可能にするには、SerializableExternalizable を拡張するか、カスタム Externalizer を提供します。

3.7.3. 通知のスキップ

サーバーからイベント通知を取得しなくても、リモート API メソッドを呼び出してオペレーションを実行する際に、SKIP_LISTENER_NOTIFICATION フラグを含めます。たとえば、値を作成または変更する際のリスナーの通知を防ぐには、フラグを以下のように設定します。

remoteCache.withFlags(Flag.SKIP_LISTENER_NOTIFICATION).put(1, "one");

3.7.4. イベントのカスタマイズ

デフォルトで生成されるイベントには、イベントを関連させるのに十分な情報が含まれていますが、送信コストを削減するために情報を詰め込みすぎないようにしています。必要に応じて、イベントに含まれる情報は、値などの詳細情報を含むか、より少ない情報を含めるためにカスタム化できます。このカスタマイズは、CacheEventConverterFactory によって生成された CacheEventConverter インスタンスを使用して行われます。

import org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory;
import org.infinispan.notifications.cachelistener.filter.CacheEventConverter;
import org.infinispan.filter.NamedFactory;

@NamedFactory(name = "static-converter")
class StaticConverterFactory implements CacheEventConverterFactory {
   final CacheEventConverter<Integer, String, CustomEvent> staticConverter = new StaticCacheEventConverter();
   public CacheEventConverter<Integer, String, CustomEvent> getConverter(final Object[] params) {
      return staticConverter;
   }
}

// Serializable, Externalizable or marshallable with Infinispan Externalizers
// needed when running in a cluster
class StaticCacheEventConverter implements CacheEventConverter<Integer, String, CustomEvent>, Serializable {
   public CustomEvent convert(Integer key, String oldValue, Metadata oldMetadata, String newValue, Metadata newMetadata, EventType eventType) {
      return new CustomEvent(key, newValue);
   }
}

// Needs to be Serializable, Externalizable or marshallable with Infinispan Externalizers
// regardless of cluster or local caches
static class CustomEvent implements Serializable {
   final Integer key;
   final String value;
   CustomEvent(Integer key, String value) {
      this.key = key;
      this.value = value;
   }
}

上記の例では、コンバーターは、イベント内の値とキーを含む新しいカスタムイベントを生成します。これにより、デフォルトのイベントと比べて大量のイベントペイロードが発生しますが、フィルターと組み合わせると、ネットワークの帯域幅コストを減らすことができます。

警告

コンバーターのターゲットタイプは、Serializable または Externalizable のいずれかである必要があります。この特定のコンバーターの場合、デフォルトの Hot Rod クライアントマーシャラーではサポートされないため、デフォルトで Externalizer を提供しません。

カスタムイベントの処理には、以前に実証されたものに対して、若干異なるクライアントリスナーの実装が必要になります。より正確な状態に戻すには、ClientCacheEntryCustomEvent インスタンスを処理する必要があります。

import org.infinispan.client.hotrod.annotation.*;
import org.infinispan.client.hotrod.event.*;

@ClientListener
public class CustomEventPrintListener {

   @ClientCacheEntryCreated
   @ClientCacheEntryModified
   @ClientCacheEntryRemoved
   public void handleCustomEvent(ClientCacheEntryCustomEvent<CustomEvent> e) {
      System.out.println(e);
   }

}

コールバックで受け取った ClientCacheEntryCustomEvent は、getEventData メソッドを介してカスタムイベントを公開し、getType メソッドは、生成されたイベントがキャッシュエントリーの作成、変更、または削除の結果であったかどうかに関する情報を提供します。

フィルタリングと同様に、リスナーをこのコンバーターファクトリーに登録できるようにするには、ファクトリーに一意の名前を付ける必要があり、Hot Rod サーバーに名前とキャッシュイベントコンバーターファクトリーインスタンスを接続する必要があります。

  1. コンバーターの実装を含む JAR ファイルを作成します。

    キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで useRawData が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。

  2. JAR ファイル内で META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory ファイルを作成し、コンバータークラス実装の完全修飾クラス名を作成します。
  3. JAR ファイルを Data Grid サーバーのインストールディレクトリーの server/lib ディレクトリーに追加します。
  4. ファクトリー名を @ClientListener アノテーションに追加して、クライアントリスナーをこのコンバーターファクトリーとリンクします。

    @ClientListener(converterFactoryName = "static-converter")
    public class CustomEventPrintListener { ... }
  5. リスナーをサーバーに登録します。

    RemoteCache<?, ?> cache = ...
    cache.addClientListener(new CustomEventPrintListener());

リスナーの登録時に提供されたパラメーターを基に変換する動的コンバーターインスタンスもあります。コンバーターは、コンバーターファクトリーによって受け取ったパラメーターを使用してこのオプションを有効にします。以下に例を示します。

import org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory;
import org.infinispan.notifications.cachelistener.filter.CacheEventConverter;

@NamedFactory(name = "dynamic-converter")
class DynamicCacheEventConverterFactory implements CacheEventConverterFactory {
   public CacheEventConverter<Integer, String, CustomEvent> getConverter(final Object[] params) {
      return new DynamicCacheEventConverter(params);
   }
}

// Serializable, Externalizable or marshallable with Infinispan Externalizers needed when running in a cluster
class DynamicCacheEventConverter implements CacheEventConverter<Integer, String, CustomEvent>, Serializable {
   final Object[] params;

   DynamicCacheEventConverter(Object[] params) {
      this.params = params;
   }

   public CustomEvent convert(Integer key, String oldValue, Metadata oldMetadata,
         String newValue, Metadata newMetadata, EventType eventType) {
      // If the key matches a key given via parameter, only send the key information
      if (params[0].equals(key))
         return new CustomEvent(key, null);

      return new CustomEvent(key, newValue);
   }
}

変換を行うために必要な動的パラメーターは、リスナーが登録されたときに提供されます。

RemoteCache<?, ?> cache = ...
cache.addClientListener(new EventPrintListener(), null, new Object[]{1});
警告

コンバーターインスタンスは、クラスターにデプロイされるときにマーシャル可能である必要があります。これにより、リスナーの登録先の別のノードで生成された場合でも、イベントが生成される際に変換が適切に行われるようにします。それらをマーシャリング可能にするには、SerializableExternalizable を拡張するか、カスタム Externalizer を提供します。

3.7.5. フィルターとカスタムイベント

イベントのフィルタリングとカスタマイズの両方を実行する場合、org.infinispan.notifications.cachelistener.filter.CacheEventFilterConverter を実装する方が簡単です。これにより、1 つのステップでフィルターとカスタマイズの両方を実行できます。便宜上、org.infinispan.notifications.cachelistener.filter.CacheEventFilterConverter を直接実装するのではなく、org.infinispan.notifications.cachelistener.filter.AbstractCacheEventFilterConverter を拡張することが推奨されます。以下に例を示します。

import org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory;
import org.infinispan.notifications.cachelistener.filter.CacheEventConverter;

@NamedFactory(name = "dynamic-filter-converter")
class DynamicCacheEventFilterConverterFactory implements CacheEventFilterConverterFactory {
   public CacheEventFilterConverter<Integer, String, CustomEvent> getFilterConverter(final Object[] params) {
      return new DynamicCacheEventFilterConverter(params);
   }
}

// Serializable, Externalizable or marshallable with Infinispan Externalizers needed when running in a cluster
//
class DynamicCacheEventFilterConverter extends AbstractCacheEventFilterConverter<Integer, String, CustomEvent>, Serializable {
   final Object[] params;

   DynamicCacheEventFilterConverter(Object[] params) {
      this.params = params;
   }

   public CustomEvent filterAndConvert(Integer key, String oldValue, Metadata oldMetadata,
         String newValue, Metadata newMetadata, EventType eventType) {
      // If the key matches a key given via parameter, only send the key information
      if (params[0].equals(key))
         return new CustomEvent(key, null);

      return new CustomEvent(key, newValue);
   }
}

フィルターとコンバーターと同様に、この組み合わせたフィルター/変換ファクトリーでリスナーを登録するには、ファクトリーに @NamedFactory アノテーション経由で一意の名前が付与される必要があります。また、Hot Rod サーバーは名前とキャッシュイベントコンバーターファクトリーインスタンスと共にプラグインする必要があります。

  1. コンバーターの実装を含む JAR ファイルを作成します。

    キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで useRawData が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。

  2. JAR ファイル内で META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventFilterConverterFactory ファイルを作成し、コンバータークラス実装の完全修飾クラス名を作成します。
  3. JAR ファイルを Data Grid サーバーのインストールディレクトリーの server/lib ディレクトリーに追加します。

クライアントの観点からすると、組み合わせたフィルターとコンバータークラスを使用できるようにするには、クライアントリスナーは同じフィルターファクトリーとコンバーターファクトリー名を定義する必要があります。以下に例を示します。

@ClientListener(filterFactoryName = "dynamic-filter-converter", converterFactoryName = "dynamic-filter-converter")
public class CustomEventPrintListener { ... }

上記の例で必要な動的パラメーターは、リスナーが filter パラメーターまたは converter パラメーターのいずれかに登録されている場合に提供されます。フィルターパラメーターが空でない場合は、それらが使用されます。それ以外の場合は、コンバーターパラメーターは以下のようになります。

RemoteCache<?, ?> cache = ...
cache.addClientListener(new CustomEventPrintListener(), new Object[]{1}, null);

3.7.6. イベントマーシャリング

Hot Rod サーバーは、異なる形式でデータを保存できますが、Java Hot Rod クライアントユーザーは、タイプ化されたオブジェクトで機能する CacheEventConverter インスタンスまたは CacheEventFilter インスタンスを開発できます。デフォルトでは、フィルターとコンバーターは、データを POJO (application/x-java-object) として使用しますが、filter/converter からメソッド format() を上書きすることで、希望の形式を上書きすることができます。形式が null を返す場合、フィルター/変換は保存時にデータを受け取ります。

Hot Rod Java クライアントは、異なる org.infinispan.commons.marshall.Marshaller インスタンスを使用するように設定できます。これ CacheEventConverter インスタンスや CacheEventFilter インスタンスをデプロイしたり、コンテンツをマーシャリングしたりするのではなく、Java オブジェクトでフィルター/変換できるようにするには、サーバーはオブジェクトとマーシャラーで生成されるバイナリー形式の間で変換できるようにする必要があります。

Marshaller インスタンスのサーバー側のデプロイするには、CacheEventConverter インスタンスまたは CacheEventFilter インスタンスをデプロイするのに使用されるものと同様の方法に従います。

  1. コンバーターの実装を含む JAR ファイルを作成します。
  2. JAR ファイル内で META-INF/services/org.infinispan.commons.marshall.Marshaller ファイルを作成し、フィルタークラス実装の完全修飾クラス名を作成します。
  3. JAR ファイルを Data Grid サーバーのインストールディレクトリーの server/lib ディレクトリーに追加します。

Marshaller は個別の jar または CacheEventConverter インスタンスおよび/または CacheEventFilter インスタンスと同じ jar にデプロイできることに注意してください。

3.7.6.1. Protostream マーシャラーのデプロイ

キャッシュが Protobuf コンテンツを保存する場合は、Hot Rod クライアントで ProtoStream マーシャラーを使用する際に発生する場合は、サーバーで形式がすでにサポートされているため、カスタムマーシャラーをデプロイする必要はありません。Protobuf 形式から JSON や POJO などの最も一般的な形式に変換するトランスコーダーがあります。

これらのキャッシュでフィルター/変換を使用し、バイナリー Protobuf データではなく Java オブジェクトでフィルター/変換を使用すると、追加の ProtoStream マーシャラーを設定し、フィルタリング/変換の前にデータをアンマーシャリングできるようにする必要があります。これには、Data Grid サーバー設定の一部として、必要な SerializationContextInitializer(s) を設定する必要があります。

詳細は、ProtoStream を参照してください。

3.7.7. リスナーの状態の処理

クライアントリスナーアノテーションには、リスナーの追加時またはリスナーのフェイルオーバー時に状態がクライアントに送信されるかどうかを指定する任意の includeCurrentState 属性があります。

デフォルトでは、includeCurrentState は false ですが、true に設定され、クライアントリスナーがデータが含まれるキャッシュに追加されると、サーバーはキャッシュの内容を繰り返し処理し、各エントリーのイベント (設定されている場合はカスタムイベント) を ClientCacheEntryCreated としてクライアントに送信します。これにより、クライアントは既存のコンテンツに基づいて一部のローカルデータ構造をビルドできます。コンテンツが繰り返されると、キャッシュの更新を受け取るため、イベントは通常どおり受信されます。キャッシュがクラスター化されている場合、クラスター全体のコンテンツ全体が繰り返し処理されます。

3.7.8. リスナーの障害処理

Hot Rod クライアントがクライアントリスナーを登録すると、クラスターの単一ノードになります。そのノードに障害が発生すると、Java Hot Rod クライアントは透過的に検出し、別のノードに失敗したノードに登録されているすべてのリスナーをフェイルオーバーします。

このフェイルオーバー中に、クライアントはいくつかのイベントを見逃す可能性があります。これらのイベントが不足しないように、クライアントリスナーアノテーションには includeCurrentState という任意のパラメーターが含まれます。これは、フェイルオーバーの実行時に、キャッシュの内容が繰り返し処理され、ClientCacheEntryCreated イベント (設定されている場合はカスタムイベント) が生成されます。デフォルトでは、includeCurrentState は false に設定されています。

コールバックを使用してフェイルオーバーイベントを処理します。

@ClientCacheFailover
public void handleFailover(ClientCacheFailoverEvent e) {
  ...
}

これは、クライアントがいくつかのデータをキャッシュしており、フェイルオーバーの結果、いくつかのイベントが見逃される可能性を考慮して、フェイルオーバーイベントを受信したときにローカルにキャッシュされたデータを消去することを決定し、フェイルオーバーイベントの後にキャッシュ全体のコンテンツに対するイベントを受信することを知っているような場合に非常に便利です。

3.8. Hot Rod Java クライアントトランザクション

JTA {tx} で Hot Rod クライアントを設定および使用できます。

トランザクションに参加するために、Hot Rod クライアントは、対話する {tm} と、{sync} または {xa} インターフェイスを介してトランザクションに参加するかどうかを要求します。

重要

トランザクションは、クライアントが準備フェーズでエントリーへの書き込みロックを取得するという点で最適化されます。データの不整合を回避するには、トランザクションとの競合を検出 を必ずお読みください。

3.8.1. サーバーの設定

クライアントが JTA トランザクション に参加するには、サーバーのキャッシュもトランザクションである必要があります。

次のサーバー設定が必要です。それ以外の場合、トランザクションはロールバックのみになります。

  • 分離レベルは REPEATABLE_READ である必要があります。
  • ロックモードは PESSIMISTIC である必要があります。今後のリリースでは、OPTIMISTIC ロックモードがサポートされます。
  • トランザクションモードは、NON_XA または NON_DURABLE_XA である必要があります。Hot Rod トランザクションはパフォーマンスが低下するため、FULL_XA を使用しないでください。

以下に例を示します。

<replicated-cache name="hotrodReplTx">
  <locking isolation="REPEATABLE_READ"/>
  <transaction mode="NON_XA" locking="PESSIMISTIC"/>
</replicated-cache>

Hot Rod トランザクションには、独自の復旧メカニズムがあります。

3.8.2. Hot Rod クライアントの設定

{rcm} の作成時に、{rc} が使用するデフォルトの {tm} および {tx-mode} を設定できます。

{rcm} を使用すると、以下の例のように、トランザクションキャッシュに設定を 1 つだけ作成できます。

org.infinispan.client.hotrod.configuration.ConfigurationBuilder cb = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
//other client configuration parameters
cb.transaction().transactionManagerLookup(GenericTransactionManagerLookup.getInstance());
cb.transaction().transactionMode(TransactionMode.NON_XA);
cb.transaction().timeout(1, TimeUnit.MINUTES)
RemoteCacheManager rmc = new RemoteCacheManager(cb.build());

上記の設定は、リモートキャッシュのすべてのインスタンスに適用されます。異なる設定をリモートキャッシュインスタンスに適用する必要がある場合は、RemoteCache 設定をオーバーライドできます。リモートCacheManager 設定の上書き を参照してください。

設定パラメーターに関するドキュメントは、{cb} Javadoc を参照してください。

以下の例のように、プロパティーファイルを使用して Java Hot Rod クライアントを設定することもできます。

infinispan.client.hotrod.transaction.transaction_manager_lookup = org.infinispan.client.hotrod.transaction.lookup.GenericTransactionManagerLookup
infinispan.client.hotrod.transaction.transaction_mode = NON_XA
infinispan.client.hotrod.transaction.timeout = 60000

3.8.2.1. TransactionManagerLookup インターフェイス

TransactionManagerLookup は {tm} を取得するためのエントリーポイントを提供します。

TransactionManagerLookup の の利用可能な実装:

{gtml}
Java EE アプリケーションサーバーで実行している {tm} を見つけるルックアップクラス。{tm} が見つからない場合は、デフォルトで {rtm} に設定されます。これは、Hot Rod Java クライアントのデフォルトです。
ヒント

ほとんどの場合、{gtml} が適しています。しかし、カスタム TransactionManager を統合する必要がある場合は、TransactionManagerLookup インターフェイスを実装できます。

{rtml}
他の実装が利用できない場合は、基本および揮発性の {tm} です。この実装には、同時トランザクションと復元を処理するときに重大な制限があることに注意してください。

3.8.3. トランザクションモード

{tx-mode} は、{rc} が {tm} と相互作用する方法を制御します。

重要

Data Grid サーバーとクライアントアプリケーションの両方でトランザクションモードを設定します。クライアントが非トランザクションキャッシュでトランザクション操作を実行しようとすると、ランタイム例外が発生する可能性があります。

トランザクションモードは、Data Grid 設定とクライアント設定の両方で同じです。クライアントで以下のモードを使用します。サーバーの Data Grid 設定スキーマを参照してください。

NONE
{rc} は {tm} と相互作用しません。これはデフォルトのモードであり、非トランザクションです。
NON_XA
{rc} は、{sync} を介して {tm} と対話します。
NON_DURABLE_XA
{rc} は {xa} を介して {tm} と対話します。復元機能は無効になっています。
FULL_XA
{rc} は {xa} を介して {tm} と対話します。復元機能が有効になっています。XaResource.recover() メソッドを呼び出して、リカバリーするトランザクションを取得します。

3.8.4. キャッシュインスタンスの設定の上書き

{rcm} はキャッシュインスタンスごとに異なる設定をサポートしないため、ただし、{rcm} には、以下のように {rc} インスタンスを返し、一部の設定パラメーターを上書きすることができる getCache (String) メソッドが含まれています。

getCache(String cacheName, TransactionMode transactionMode)
{rc} を返し、設定された {tx-mode} をオーバーライドします。
getCache(String cacheName, boolean forceReturnValue, TransactionMode transactionMode)
以前と同じですが、書き込み操作の戻り値を強制することもできます。
getCache(String cacheName, TransactionManager transactionManager)
{rc} を返し、設定済みの {tm} を上書きします。
getCache(String cacheName, boolean forceReturnValue, TransactionManager transactionManager)
以前と同じですが、書き込み操作の戻り値を強制することもできます。
getCache(String cacheName, TransactionMode transactionMode, TransactionManager transactionManager)
{rc} を返し、設定済みの {tm} および {tx-mode} をオーバーライドします。transactionManager または transactionMode が null の場合、設定された値を使用します。
getCache(String cacheName, boolean forceReturnValue, TransactionMode transactionMode, TransactionManager transactionManager)
以前と同じですが、書き込み操作の戻り値を強制することもできます。
注記

getCache (String) メソッドは、トランザクションであるかどうかに関係なく、{rc} インスタンスを返します。{rc} には、キャッシュが使用する {tm} を返す getTransactionManager () メソッドが含まれています。{rc} がトランザクションではない場合、メソッドは null を返します。

3.8.5. トランザクションとの競合の検出

トランザクションはキーの初期値を使用して競合を検出します。

たとえば、トランザクションの開始時に k の値は v となります。準備フェーズでは、トランザクションはサーバーから "k" を取得して値を読み取ります。値が変更された場合、トランザクションは競合を回避するためにロールバックします。

注記

トランザクションはバージョンを使用して、値の等価性を確認する代わりに変更を検出します。

forceReturnValue パラメーターは、RemoteCache への書き込み操作を制御し、競合を回避するのに役立ちます。次の値があります。

  • true の場合、{tm} は書き込み操作を実行する前にサーバーから最新の値を取得します。ただし、forceReturnValue パラメーターは、キーの初回アクセスの操作にのみ適用されます。
  • false の場合、{tm} は書き込み操作を実行する前にサーバーから最新の値を取得しません。
注記

このパラメーターは、最新の値が必要なため、replaceputIfAbsent などの 条件付き 書き込み操作には影響しません。

以下のトランザクションは、forceReturnValue パラメーターが競合する書き込み操作を防ぐ例を提供します。

トランザクション 1 (TX1)

RemoteCache<String, String> cache = ...
TransactionManager tm = ...

tm.begin();
cache.put("k", "v1");
tm.commit();

トランザクション 2 (TX2)

RemoteCache<String, String> cache = ...
TransactionManager tm = ...

tm.begin();
cache.put("k", "v2");
tm.commit();

この例では、TX1 と TX2 が並行して実行されます。k の初期値は v です。

  • forceReturnValue = true の場合、cache.put() 操作はサーバーから TX1 と TX2 の両方のサーバーから k の値を取得します。最初に k のロックを取得するトランザクションはコミットします。他のトランザクションは、k が v 以外の値を持っていることをトランザクションが検出できるため、コミットフェーズ中にロールバックします。
  • forceReturnValue = false の場合 cache.put() オペレーションはサーバーから "k" の値を取得せず、null を返します。TX1 と TX2 の両方が正常にコミットされ、競合が生じます。これは、"k"の初期値が変更されたことをトランザクションが検知できないために発生します。

以下のトランザクションは、cache.put() オペレーションを行う前に K の値を読み取る cache.get() オペレーションが含まれます。

トランザクション 1 (TX1)

RemoteCache<String, String> cache = ...
TransactionManager tm = ...

tm.begin();
cache.get("k");
cache.put("k", "v1");
tm.commit();

トランザクション 2 (TX2)

RemoteCache<String, String> cache = ...
TransactionManager tm = ...

tm.begin();
cache.get("k");
cache.put("k", "v2");
tm.commit();

上記の例では、TX1 および TX2 の両方が鍵を読み取るため、forceReturnValue パラメーターは有効になりません。1 つのトランザクションがコミットし、もう 1 つのトランザクションがロールバックします。ただし、cache.get() 操作には追加のサーバー要求が必要です。サーバーリクエストが非効率な cache.put() オペレーションの戻り値が必要ない場合。

3.8.6. 設定済みトランザクションマネージャーおよびトランザクションモードの使用

以下の例は、RemoteCacheManager で設定した TransactionManager および TransactionMode を使用する方法を示しています。

//Configure the transaction manager and transaction mode.
org.infinispan.client.hotrod.configuration.ConfigurationBuilder cb = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
cb.transaction().transactionManagerLookup(RemoteTransactionManagerLookup.getInstance());
cb.transaction().transactionMode(TransactionMode.NON_XA);

RemoteCacheManager rcm = new RemoteCacheManager(cb.build());

//The my-cache instance uses the RemoteCacheManager configuration.
RemoteCache<String, String> cache = rcm.getCache("my-cache");

//Return the transaction manager that the cache uses.
TransactionManager tm = cache.getTransactionManager();

//Perform a simple transaction.
tm.begin();
cache.put("k1", "v1");
System.out.println("K1 value is " + cache.get("k1"));
tm.commit();

3.8.7. トランザクションマネージャーの上書き

以下の例は、getCache メソッドで TransactionManager を上書きする方法を示しています。

//Configure the transaction manager and transaction mode.
org.infinispan.client.hotrod.configuration.ConfigurationBuilder cb = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
cb.transaction().transactionManagerLookup(RemoteTransactionManagerLookup.getInstance());
cb.transaction().transactionMode(TransactionMode.NON_XA);

RemoteCacheManager rcm = new RemoteCacheManager(cb.build());

//Define a custom TransactionManager.
TransactionManager myCustomTM = ...

//Override the TransactionManager for the my-cache instance. Use the default configuration if null is returned.
RemoteCache<String, String> cache = rcm.getCache("my-cache", null, myCustomTM);

//Perform a simple transaction.
myCustomTM.begin();
cache.put("k1", "v1");
System.out.println("K1 value is " + cache.get("k1"));
myCustomTM.commit();

3.8.8. トランザクションモードの上書き

以下の例は、getCache メソッドで TransactionMode を上書きする方法を示しています。

//Configure the transaction manager and transaction mode.
org.infinispan.client.hotrod.configuration.ConfigurationBuilder cb = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
cb.transaction().transactionManagerLookup(RemoteTransactionManagerLookup.getInstance());
cb.transaction().transactionMode(TransactionMode.NON_XA);

RemoteCacheManager rcm = new RemoteCacheManager(cb.build());

//Override the transaction mode for the my-cache instance.
RemoteCache<String, String> cache = rcm.getCache("my-cache", TransactionMode.NON_DURABLE_XA, null);

//Return the transaction manager that the cache uses.
TransactionManager tm = cache.getTransactionManager();

//Perform a simple transaction.
tm.begin();
cache.put("k1", "v1");
System.out.println("K1 value is " + cache.get("k1"));
tm.commit();

法律上の通知

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.