Hot Rod Java クライアントガイド
Hot Rod Java クライアントの設定および使用
概要
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 リポジトリーをダウンロードし、インストールします。
手順
- Red Hat カスタマーポータルにログインします。
- Software Downloads for Data Grid に移動します。
- Red Hat Data Grid 8.1 Maven リポジトリーをダウンロードします。
- アーカイブされた Maven リポジトリーをローカルファイルシステムにデプロイメントします。
-
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 形式であり、モジュールとコンポーネントの依存関係、ビルドの順序、および結果となるプロジェクトのパッケージ化と出力のターゲットを記述します。
手順
-
プロジェクト
pom.xml
を開いて編集します。 -
正しい Data Grid バージョンで
version.infinispan
プロパティーを定義します。 dependencyManagement
セクションにinfinispan-bom
を含めます。BOM(Bill of Materials) は、依存関係バージョンを制御します。これにより、バージョンの競合が回避され、プロジェクトに依存関係として追加する Data Grid アーティファクトごとにバージョンを設定する必要がなくなります。
-
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 インテリジェンスを使用するクライアントは、すべてのリクエストに対してリクエストバランシングを使用します。デフォルトのバランシングストラテジーはラウンドロビンであるため、トポロジー対応のクライアントは常にラウンドロビン順でサーバーにリクエストを送信します。
たとえば、s1
、s2
、s3
は 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 認証メカニズムをサポートします。
認証メカニズム | 説明 | 関連する詳細 |
---|---|---|
|
プレーンテキスト形式の認証情報を使用します。 |
|
|
ハッシュアルゴリズムとナンス値を使用します。ホットロッドコネクターは、強度の順に、 |
|
|
ハッシュアルゴリズムとナンス値に加えてソルト値を使用します。ホットロッドコネクターは、 |
|
|
Kerberos チケットを使用し、Kerberos ドメインコントローラーが必要です。対応する |
|
|
Kerberos チケットを使用し、Kerberos ドメインコントローラーが必要です。対応する |
|
| クライアント証明書を使用します。 |
|
|
OAuth トークンを使用し、 |
|
2.4.2. GSSAPI ログインコンテキストの作成
GSSAPI メカニズムを使用するには、LoginContextを作成して、Hot Rod クライアント Ticket Granting Ticket (TGT) を取得できるようにする必要があります。
手順
ログイン設定ファイルでログインモジュールを定義します。
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; };
次のシステムプロパティーを設定します。
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 証明書チェーン
手順
- サーバー証明書チェーンの一部で Java キーストアを作成します。ほとんどの場合、CA の公開証明書を使用する必要があります。
-
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 クライアントを入手している。
手順
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());
-
XMLStringConfiguration
クラスを使用して、XML 形式でキャッシュ定義を追加します。 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."); }
次の例のように、
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 RodConfigurationBuilder
クラスでキャッシュごとの設定を作成します。
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"));
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
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 の境界内にニアキャッシュのサイズを保持する必要があります。
- ニアキャッシュの無効化メッセージにより書き込み操作のパフォーマンスが低下します。
手順
-
必要なキャッシュのクライアント設定で、ニアキャッシュモードを
INVALIDATED
に設定します。 - エントリーの最大数を指定して、ニアキャッシュのサイズを定義します。
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 クライアントを設定します。
手順
-
org.infinispan.commons.marshall.Marshaller
インターフェイスを実装します。 - Hot Rod クライアント設定でクラスの完全修飾名を指定します。
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 をマッピングします。RemoteCacheManager は DefaultCacheManager に対応します(どちらも CacheContainer を実装します)。この共通 API により、ローカル呼び出しから Hot Rod を介したリモート呼び出しへの移行が容易になります。必要なのは、DefaultCacheManager と RemoteCacheManager を切り替えることだけです。これは、両方が継承する共通の CacheContainer インターフェイスによってさらに簡素化されます。
3.2. RemoteCache API
コレクションメソッド keySet
、entrySet
、および 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
です。keySet
、entrySet
、および 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 サーバーインスタンスにデプロイします。
手順
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. } } }
META-INF/services/org.infinispan.filter.KeyValueFilterConverterFactory
ファイルが含まれる JAR を作成します。このファイルには、フィルターファクトリークラス実装の完全修飾クラス名を含める必要があります。フィルターがカスタムのキー/値クラスを使用する場合は、フィルターがキーや値のインスタンスを正しくアンマーシャリングできるように、それらを JAR ファイルに含める必要があります。
-
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)
メソッドによって返される InputStream
は VersionedMetadata
インターフェイスを実装しているため、以下のようにバージョンと有効期限の情報を取得できます。
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
インスタンスは、影響を受けるキーとエントリーのバージョンに関する情報を提供します。このバージョンは、replaceWithVersion
、removeWithVersion
などのサーバー上で条件付き操作を呼び出すために使用できます。
ClientCacheEntryRemovedEvent
イベントは、削除操作が成功した場合にのみ送信されます。つまり、削除オペレーションが呼び出されても、エントリーが見つからないか、エントリーを削除する必要がない場合は、イベントが生成されません。エントリーが削除されていなくても、削除されたイベントに関心のあるユーザーは、このようなイベントを生成するイベントのカスタマイズロジックを開発できます。詳細は、クライアントイベントのカスタマイズ セクションを参照してください。
ClientCacheEntryCreatedEvent
、ClientCacheEntryModifiedEvent
、および 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 サーバーに名前とキャッシュイベントフィルターファクトリーインスタンスを接続する必要があります。
フィルターの実装を含む JAR ファイルを作成します。
キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで
useRawData
が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。-
JAR ファイル内で
META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventFilterFactory
ファイルを作成し、フィルタークラス実装の完全修飾クラス名を作成します。 -
JAR ファイルを Data Grid サーバーのインストールディレクトリーの
server/lib
ディレクトリーに追加します。 ファクトリー名を
@ClientListener
アノテーションに追加して、クライアントリスナーをこのキャッシュイベントフィルターファクトリーとリンクします。@ClientListener(filterFactoryName = "static-filter") public class EventPrintListener { ... }
リスナーをサーバーに登録します。
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);
フィルターインスタンスは、クラスターにデプロイされるときにマーシャル可能である必要があります。これにより、リスナーの登録先の別のノードで生成された場合でも、イベントが生成される際にフィルターが適切に行われるようにします。それらをマーシャリング可能にするには、Serializable
、Externalizable
を拡張するか、カスタム 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 サーバーに名前とキャッシュイベントコンバーターファクトリーインスタンスを接続する必要があります。
コンバーターの実装を含む JAR ファイルを作成します。
キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで
useRawData
が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。-
JAR ファイル内で
META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory
ファイルを作成し、コンバータークラス実装の完全修飾クラス名を作成します。 -
JAR ファイルを Data Grid サーバーのインストールディレクトリーの
server/lib
ディレクトリーに追加します。 ファクトリー名を
@ClientListener
アノテーションに追加して、クライアントリスナーをこのコンバーターファクトリーとリンクします。@ClientListener(converterFactoryName = "static-converter") public class CustomEventPrintListener { ... }
リスナーをサーバーに登録します。
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});
コンバーターインスタンスは、クラスターにデプロイされるときにマーシャル可能である必要があります。これにより、リスナーの登録先の別のノードで生成された場合でも、イベントが生成される際に変換が適切に行われるようにします。それらをマーシャリング可能にするには、Serializable
、Externalizable
を拡張するか、カスタム 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 サーバーは名前とキャッシュイベントコンバーターファクトリーインスタンスと共にプラグインする必要があります。
コンバーターの実装を含む JAR ファイルを作成します。
キャッシュがカスタムのキー/値クラスを使用する場合は、コールバックを正しくマーシャリングされていないキー/値インスタンスで実行できるように、これらを JAR に含める必要があります。クライアントリスナーで
useRawData
が有効になっている場合、コールバックのキー/値インスタンスはバイナリー形式で提供されるため、これは必要ありません。-
JAR ファイル内で
META-INF/services/org.infinispan.notifications.cachelistener.filter.CacheEventFilterConverterFactory
ファイルを作成し、コンバータークラス実装の完全修飾クラス名を作成します。 -
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
インスタンスをデプロイするのに使用されるものと同様の方法に従います。
- コンバーターの実装を含む JAR ファイルを作成します。
-
JAR ファイル内で
META-INF/services/org.infinispan.commons.marshall.Marshaller
ファイルを作成し、フィルタークラス実装の完全修飾クラス名を作成します。 -
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} は書き込み操作を実行する前にサーバーから最新の値を取得しません。
このパラメーターは、最新の値が必要なため、replace
や putIfAbsent
などの 条件付き 書き込み操作には影響しません。
以下のトランザクションは、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();