これは、なにをしたくて書いたもの?
Infinispan 11.0.0.Finalから、Infinispan Serverへの接続情報や設定をURIとして表現できるようになっています。
Blog: Hot Rod URI - Infinispan
Blog: Infinispan 11.0.0.Final - Infinispan
ちょっと興味があったので、そろそろ試しておこうかな、と。
Hot Rod URI
これまで、ConfigurationBuilder
やhotrod.properties
で指定した内容を、URIとして指定できる機能です。
フォーマットは、こちら。
hotrod[s]://[username:password]@host[:port][,host[:port]…][?property=value[&property=value…]]
認証が必要な場合は、ホスト名の前に[username:password]@
が入ります。接続先のホストは、,
区切りで複数指定することが
できます。
それ以外のプロパティは、QueryStringの形式で指定します。この時、hotrod.properties
で指定していたinfinispan.client.hotrod
という
プレフィックスは不要になります。
このURIは、ConfigurationBuilder
で指定するか、hotrod.properties
のinfinispan.client.hotrod.uri
として指定します。
見たところ、こちらのガイドにはHot Rod URIの記述はないようです。
現時点では、org.infinispan.client.hotrod.configuration
パッケージのサマリーを見るのが良さそうですね。
org.infinispan.client.hotrod.configuration (Infinispan JavaDoc 12.0.2.Final API)
では、試してみましょう。
環境
今回の環境は、こちらです。
$ java --version openjdk 11.0.10 2021-01-19 OpenJDK Runtime Environment (build 11.0.10+9-Ubuntu-0ubuntu1.20.04) OpenJDK 64-Bit Server VM (build 11.0.10+9-Ubuntu-0ubuntu1.20.04, mixed mode, sharing) $ mvn --version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.10, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-70-generic", arch: "amd64", family: "unix"
Infinispan Serverは、12.0.2.Finalを使います。3つインスタンスを用意し、172.17.0.2〜172.17.0.4で動作しているものとします。
Infinispan Server側の準備
Infinispan Serverへのアクセスは、認証を必須にすることにします。
ユーザーを作成。グループはadmin
とします。
$ bin/cli.sh user create ispn-user -p ispn-password -g admin
続いて、server/conf/infinispan.xml
を編集します。
エンドポイントの設定は、こちら。
<endpoints socket-binding="default" security-realm="default"> <hotrod-connector> <authentication> <sasl qop="auth" server-name="infinispan"/> </authentication> </hotrod-connector> <rest-connector /> </endpoints>
Cacheの設定は、admin
グループに全権限を与える簡易なものにしておきます。Cache自体は、Distributed Cacheを使います。
<cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name:cluster}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/> <security> <authorization> <identity-role-mapper/> <role name="ispn-user" permissions="ALL"/> </authorization> </security> <distributed-cache name="myCache"> <security> <authorization roles="ispn-user"/> </security> </distributed-cache> </cache-container>
ここまでやったら、Infinispan Serverを再起動します。
クラスタには、3つNodeが存在している状態です。
$ bin/cli.sh -c http://ispn-user:ispn-password@localhost:11222 [ae83336a35bf-19567@cluster//containers/default]> ls /cluster 2084c2102a21-13797 cb222c8eeb1b-60045 ae83336a35bf-19567
テストコード準備
<dependencies> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-client-hotrod</artifactId> <version>12.0.2.Final</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.7.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.19.0</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build>
今回のテーマで必須なのは、infinispan-client-hotrod
だけですね。
確認は、テストコードで行います。
src/test/java/org/littlewings/infinispan/client/connect/ConnectServerTest.java
package org.littlewings.infinispan.client.connect; import java.time.Duration; import java.util.concurrent.CompletableFuture; import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.configuration.Configuration; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; public class ConnectServerTest { // ここに、テストコードを書く }
こちらをベースに進めていきます。
Hot Rod URIを使わずに、Infinispan Serverに接続する
比較のために、まずはHot Rod URIを使わずにInfinispan Serverに接続してみましょう。
@Test public void usingMethodBasedConfiguration() { Configuration configuration = new ConfigurationBuilder() .addServers("172.17.0.2:11222;172.17.0.3:11222;172.17.0.4:11222") .connectionPool() .maxActive(10) .maxWait(10000) .connectionTimeout(30000) .socketTimeout(30000) .security() .authentication() .saslMechanism("SCRAM-SHA-256") .username("ispn-user") .password("ispn-password".toCharArray()) .build(); RemoteCacheManager manager = new RemoteCacheManager(configuration); Configuration c = manager.getConfiguration(); assertThat(c.connectionPool().maxActive()).isEqualTo(10); assertThat(c.connectionPool().maxWait()).isEqualTo(10000); assertThat(c.connectionTimeout()).isEqualTo(30000); assertThat(c.socketTimeout()).isEqualTo(30000); assertThat(c.security().authentication().saslMechanism()).isEqualTo("SCRAM-SHA-256"); try { RemoteCache<String, String> cache = manager.getCache("myCache"); CompletableFuture<String> putAndGet = cache .putAsync("key1", "value1") .thenCompose(v -> cache.getAsync("key1")); assertThat(putAndGet) .succeedsWithin(Duration.ofSeconds(10)) .isEqualTo("value1"); CompletableFuture<String> removeAndGet = cache.removeAsync("key1") .thenCompose(v -> cache.getAsync("key1")); assertThat(removeAndGet) .succeedsWithin(Duration.ofSeconds(10)) .isNull(); } finally { manager.stop(); } }
設定は、こんな感じでConfigurationBuilder
で指定します。
Configuration configuration = new ConfigurationBuilder() .addServers("172.17.0.2:11222;172.17.0.3:11222;172.17.0.4:11222") .connectionPool() .maxActive(10) .maxWait(10000) .connectionTimeout(30000) .socketTimeout(30000) .security() .authentication() .saslMechanism("SCRAM-SHA-256") .username("ispn-user") .password("ispn-password".toCharArray()) .build();
設定できていることは、RemoteCacheManager
から取得できるConfiguration
を使って確認しましょう。
RemoteCacheManager manager = new RemoteCacheManager(configuration); Configuration c = manager.getConfiguration(); assertThat(c.connectionPool().maxActive()).isEqualTo(10); assertThat(c.connectionPool().maxWait()).isEqualTo(10000); assertThat(c.connectionTimeout()).isEqualTo(30000); assertThat(c.socketTimeout()).isEqualTo(30000); assertThat(c.security().authentication().saslMechanism()).isEqualTo("SCRAM-SHA-256");
ユーザー名およびパスワードは確認できませんが、これはInfinispan Serverに接続できたことをもってOKとします。
あとは、通常のInfinispanのHot Rod Clientの使い方と同じなので省略。
Hot Rod URIを使って、Infinispan Serverに接続する
続いて、Hot Rod URIを使ってInfinispan Serverに接続してみます。
@Test public void usingUri() { Configuration configuration = new ConfigurationBuilder() .uri("hotrod://ispn-user:ispn-password@172.17.0.2:11222,172.17.0.3:11222,172.17.0.4:11222?sasl_mechanism=SCRAM-SHA-256&connection_pool.max_active=10&connect_timeout=30000&socket_timeout=30000") .connectionPool() .maxWait(10000) .build(); RemoteCacheManager manager = new RemoteCacheManager(configuration); Configuration c = manager.getConfiguration(); assertThat(c.connectionPool().maxActive()).isEqualTo(10); assertThat(c.connectionPool().maxWait()).isEqualTo(10000); assertThat(c.connectionTimeout()).isEqualTo(30000); assertThat(c.socketTimeout()).isEqualTo(30000); assertThat(c.security().authentication().saslMechanism()).isEqualTo("SCRAM-SHA-256"); try { RemoteCache<String, String> cache = manager.getCache("myCache"); CompletableFuture<String> putAndGet = cache .putAsync("key1", "value1") .thenCompose(v -> cache.getAsync("key1")); assertThat(putAndGet) .succeedsWithin(Duration.ofSeconds(10)) .isEqualTo("value1"); CompletableFuture<String> removeAndGet = cache.removeAsync("key1") .thenCompose(v -> cache.getAsync("key1")); assertThat(removeAndGet) .succeedsWithin(Duration.ofSeconds(10)) .isNull(); } finally { manager.stop(); } }
先ほどの例から変わったのは、ここだけですね。
new ConfigurationBuilder() .uri("hotrod://ispn-user:ispn-password@172.17.0.2:11222,172.17.0.3:11222,172.17.0.4:11222?sasl_mechanism=SCRAM-SHA-256&connection_pool.max_active=10&connect_timeout=30000&socket_timeout=30000") .connectionPool() .maxWait(10000) .build();
ユーザー名およびパスワード、接続先のInfinispan Serverのリストはこんな感じで指定します。
ispn-user:ispn-password@172.17.0.2:11222,172.17.0.3:11222,172.17.0.4:11222
アドレス:ポート
を複数並べる時は、ConfigurationBuilder#addServers
の時は;
が区切り文字でしたが、Hot Rod URIになると
,
に変わるので注意です。
その他のプロパティは、QueryStringの形式でJavadocに記載のプロパティ名からinfinispan.client.hotrod
を除いたものを
指定します。
org.infinispan.client.hotrod.configuration (Infinispan JavaDoc 12.0.2.Final API)
?sasl_mechanism=SCRAM-SHA-256&connection_pool.max_active=10&connect_timeout=30000&socket_timeout=30000
connection_pool.max_active
のように、.
が入ってもOKです。
コネクションプールのmaxWait
のみメソッドで指定していますが、これはHot Rod URIによる指定も、メソッドによる指定も
両方を併用できることを確認しています。
RemoteCacheManager
から取得したConfiguration
へのテスト内容は先ほどと同じなので、Hot Rod URIで指定した内容が
反映できていることが確認できたことになります。
RemoteCacheManager manager = new RemoteCacheManager(configuration); Configuration c = manager.getConfiguration(); assertThat(c.connectionPool().maxActive()).isEqualTo(10); assertThat(c.connectionPool().maxWait()).isEqualTo(10000); assertThat(c.connectionTimeout()).isEqualTo(30000); assertThat(c.socketTimeout()).isEqualTo(30000); assertThat(c.security().authentication().saslMechanism()).isEqualTo("SCRAM-SHA-256");
これで、Hot Rod URIを使って設定ができたことを確認できました。
なお、Hot Rod URIをパースしているのは、このあたりです。
まとめ
前々から、接続情報をURIで指定できたらいいなーと思っていたので、これができるようになったのは良かったなと。
あと、認証設定などのいい復習になりました。
今回作成したソースコードは、こちらに置いています。
https://github.com/kazuhira-r/infinispan-getting-started/tree/master/remote-connect-uri