#chiroito ’s blog

Java を中心とした趣味の技術について

HotRod ストアを使ったWildflyのセッションレプリケーション

これまでは、リモートストアを使用して HTTP セッションを Infinispan やその商用製品である Red Hat Data Grid へオフロードしていました。ですがその方法は Wildfly 14 (JBoss EAP 7.2)から古くなったようです。新しい方法は同バージョンから導入されたelytron サブシステムと統合する HotRod プロトコルをベースとするカスタムの最適化されたキャッシュストアを使います。

24.3.10. リモートストアを使用した HTTP セッションの Red Hat Data Grid への外部化

環境

  • Wildfly 19.1
  • Infinispan 9.4.18
  • Java EE 8

今回構築する構成は以下の様な構成です。1 つの Wildfly と 2 つの Infinispan を構築します。

f:id:chiroito:20200519172347p:plain

サンプルのソースコードはこちらにあります。

GitHub - chiroito/wildfly-session-sample

手順

Infinispan の設定は何も必要ありません。Wildfly の設定をしてアプリがそれを使えるように設定をすればセッションレプリケーションできます。

手順は以下のとおりです。

  1. 接続先となる Infinispan を定義する (下図の青)
  2. remote-cache-container と remote-cluster を定義する(下図の黄色)
  3. invalidation-cache を定義する (下図の赤)
  4. アプリでキャッシュを使うように設定する
  5. アプリをデプロイする

f:id:chiroito:20200521160717p:plain

0. Infinispan を起動する。

今回は 2 ノードの Infinispan を起動します。 ダウンロードした Infinispan の zip を 2 回別の名前で解凍します。 普通に実行すると使用しているポートが被ってしまいます。それを回避するため引数に-Djboss.socket.binding.port-offsetを付与します。それぞれのディレクトリで次の様に実行します。

1つ目

bin\standalone.bat -c clustered.xml -Djboss.node.name=nodeA

2つ目

bin\standalone.bat -c clustered.xml -Djboss.node.name=nodeB -Djboss.socket.binding.port-offset=100

1. 接続先となる Infinispan を定義する

これからの作業には jboss-cliを使用します。これはwlidflyのインストール先のbin\jboss-cli.batです。jboss-cli.bat -cで起動したら以下を実行します。

batch
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=infinispan-server1:add(host=127.0.0.1, port=11222)
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=infinispan-server2:add(host=127.0.0.1, port=11322)
run-batch

2. remote-cache-container と remote-cluster を定義する

こちらも同様に Jboss-cli で以下を実行します。

batch
/subsystem=infinispan/remote-cache-container=foo:add(default-remote-cluster=bar)
/subsystem=infinispan/remote-cache-container=foo/remote-cluster=bar:add(socket-bindings=[infinispan-server1, infinispan-server2])
run-batch

3. invalidation-cache を定義する

以前の方法とはここが変りました。以前はリモートストアを使っていましたが、今回はHotRodストアを使います。

これまでの方法では以下の様にstoreremoteでした。

/subsystem=infinispan/cache-container=web/invalidation-cache=infinispan/store=remote

これからの方法では以下の様にstorehotrodになります。

/subsystem=infinispan/cache-container=web/invalidation-cache=infinispan/store=hotrod

こちらも同様に Jboss-cli で以下を実行します。

batch
/subsystem=infinispan/cache-container=web/invalidation-cache=baz:add()
/subsystem=infinispan/cache-container=web/invalidation-cache=baz/component=transaction:add(mode=BATCH)
/subsystem=infinispan/cache-container=web/invalidation-cache=baz/component=locking:add(isolation=REPEATABLE_READ)
/subsystem=infinispan/cache-container=web/invalidation-cache=baz/store=hotrod:add(remote-cache-container=foo, fetch-state=false, purge=false, passivation=false, shared=true)
run-batch

4. アプリでキャッシュを使うように設定する

アプリケーションは以下の 2 つの設定ファイルを変更します。

  • WEB-INF/web.xml
  • WEB-INF/jboss-web.xml

WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <distributable/>
</web-app>

WEB-INF/jboss-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_13_0.xsd"
           version="13.0">

    <replication-config>
        <cache-name>web.baz</cache-name>
    </replication-config>

</jboss-web>

5. アプリをデプロイする

アプリケーションをビルドして Wildfly へデプロイします。ビルドには Maven などのビルドツールを使い、デプロイはこれまで同様にjboss-cliを使います。

cd wildfly-session-sample
mvn clean package
jboss-cli.bat -c
deploy target\wildfly-session-sample.war

確認

環境構築がうまくいってアプリがちゃんとできていると Wildfly が以下の様なメッセージを出力します。

[2020-05-19 03:19:43,748] Artifact wildfly-session-sample:war: Artifact is being deployed, please wait...
(略)
15:19:44,225 WARN  [org.wildfly.clustering.web.undertow] (MSC service thread 1-7) WFLYCLWEBUT0004: Legacy <replication-config/> overriding attached distributable session management provider for wildfly-session-sample.war
15:19:44,246 INFO  [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 102) WFLYCLINF0032: Getting remote cache named 'wildfly-session-sample.war'. If it does not exist a new cache will be created from configuration template named 'transactional'; null value uses default cache configuration on the Infinispan Server.
(略)
15:19:44,282 INFO  [org.infinispan.CLUSTER] (ServerService Thread Pool -- 102) [Context=wildfly-session-sample.war] ISPN100008: Updating cache members list [laptop-tlfueb3p], topology id 2
(略)
[2020-05-19 03:19:44,510] Artifact wildfly-session-sample:war: Artifact is deployed successfully
[2020-05-19 03:19:44,510] Artifact wildfly-session-sample:war: Deploy took 762 milliseconds

以下の URL へアクセスしてみてください。

以下の場合は各設定ファイルがきちんと書かれているか、デプロイしている war ファイル内のディレクトリ構成が正しいかを確認しましょう。私は IntelliJ IDEA の Enterprise Java で war ファイルを作ったところ後者に嵌まりました・・・

デプロイした時のログがこんな場合jboss-web.xmlの設定ができていません。

[2020-05-19 03:20:19,013] Artifact wildfly-session-sample:war: Artifact is being deployed, please wait...
(略)
15:20:19,613 INFO  [org.infinispan.configuration.cache.MemoryConfigurationBuilder] (MSC service thread 1-4) ISPN000152: Passivation configured without an eviction policy being selected. Only manually evicted entities will be passivated.
15:20:19,628 INFO  [org.infinispan.configuration.cache.MemoryConfigurationBuilder] (MSC service thread 1-4) ISPN000152: Passivation configured without an eviction policy being selected. Only manually evicted entities will be passivated.
(略)
[2020-05-19 03:20:19,905] Artifact wildfly-session-sample:war: Artifact is deployed successfully
[2020-05-19 03:20:19,905] Artifact wildfly-session-sample:war: Deploy took 892 milliseconds

このログの(略)に挟まれているログすら出ない場合は web.xmlの設定ができていません。

参考

24.3.9. HTTP セッションの Red Hat Data Grid への外部化

OpenShift のクラスタモニタリングスタックを Infra ノードで動かす

OpenShift のクラスタモニタリングスタックの設定を変更するには、クラスタモニタリングの ConfigMap を変更する必要があります。この ConfigMap が存在しない場合は、参考の URL にあるマニュアルにある通り作成します。

設定をする前にまずはクラスタモニタリングスタックの設定を確認してみます。

$ oc -n openshift-monitoring get configmap cluster-monitoring-config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2020-04-23T06:47:21Z"
  name: cluster-monitoring-config
  namespace: openshift-monitoring
  resourceVersion: "368857"
  selfLink: /api/v1/namespaces/openshift-monitoring/configmaps/cluster-monitoring-config
  uid: 619c4ac8-c623-4bbc-a47b-bc158b64e5d0

以下のコマンドを使用してクラウドモニタリングスタックの ConfigMap を編集します。

$ oc -n openshift-monitoring edit configmap cluster-monitoring-config

今回は、各スタックを Infra ノードで動かすため、以下を追加します。

data:
  config.yaml: |
    prometheusOperator:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    prometheusK8s:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    alertmanagerMain:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    kubeStateMetrics:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    grafana:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    auth:
      nodeSelector:
        node-role.kubernetes.io/infra: ""

以下の様になれば大丈夫です。

$ oc -n openshift-monitoring get configmap cluster-monitoring-config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: "2020-04-23T06:47:21Z"
  name: cluster-monitoring-config
  namespace: openshift-monitoring
  resourceVersion: "368857"
  selfLink: /api/v1/namespaces/openshift-monitoring/configmaps/cluster-monitoring-config
  uid: 619c4ac8-c623-4bbc-a47b-bc158b64e5d0
data:
  config.yaml: |
    prometheusOperator:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    prometheusK8s:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    alertmanagerMain:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    kubeStateMetrics:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    grafana:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    auth:
      nodeSelector:
        node-role.kubernetes.io/infra: ""

参考

OpenShift の Router が Infra ノードで動くようにする

Infraノードを足しても OpenShift のインフラである Router が Infra ノードに移らなかったので、移るようにするメモです。

ノードは以下の様になっています。

$ oc get nodes -n openshift-machine-api
NAME                                         STATUS   ROLES          AGE   VERSION
ip-10-0-129-22.us-east-2.compute.internal    Ready    infra,worker   20h   v1.16.2
ip-10-0-132-220.us-east-2.compute.internal   Ready    master         21h   v1.16.2
ip-10-0-141-130.us-east-2.compute.internal   Ready    infra,worker   20h   v1.16.2
ip-10-0-145-141.us-east-2.compute.internal   Ready    master         21h   v1.16.2
ip-10-0-165-220.us-east-2.compute.internal   Ready    master         21h   v1.16.2
ip-10-0-166-143.us-east-2.compute.internal   Ready    worker         20h   v1.16.2
ip-10-0-169-180.us-east-2.compute.internal   Ready    worker         20h   v1.16.2

ルータのポッドを見てみます。worker ノードで動いているのが分かります。

$ oc get pods -o wide -n openshift-ingress | grep router
router-default-859fd5d9df-5vfdr  1/1   Running    0   20h   10.130.2.11   ip-10-0-166-143.us-east-2.compute.internal   <none>  <none>
router-default-859fd5d9df-8rpqs  1/1   Running    0   20h   10.129.2.12   ip-10-0-169-180.us-east-2.compute.internal   <none>  <none>

設定を見てみます。以下の様に replicas が 2 になっているため router が 2 行出力されていました。

$ oc get -n openshift-ingress-operator ingresscontrollers/default -o yaml
apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
(略)
spec:
  replicas: 2
status:
  availableReplicas: 2
(略)

インフラノードで router が動くように、oc editでこの設定を変更します。

$ oc edit -n openshift-ingress-operator ingresscontrollers/default

spec に以下を足します。

  nodePlacement:
    nodeSelector:
      matchLabels:
        node-role.kubernetes.io/infra: ""

変更後の全体像は以下の感じです。

$ oc get -n openshift-ingress-operator ingresscontrollers/default -o yaml
apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
(略)
spec:
  nodePlacement:
    nodeSelector:
      matchLabels:
        node-role.kubernetes.io/infra: ""
  replicas: 2
status:
  availableReplicas: 2
(略)

Router が再起動するので、それが落ち着くと以下の様に Infra ノードで動くようになります

$ oc get pods -o wide -n openshift-ingress | grep router
router-default-859fd5d9df-5vfdr  1/1   Running    0   20h   10.130.2.11   ip-10-0-129-22.us-east-2.compute.internal   <none>  <none>
router-default-859fd5d9df-8rpqs  1/1   Running    0   20h   10.129.2.12   ip-10-0-141-130.us-east-2.compute.internal  <none>  <none>