CLOVER🍀

That was when it all began.

Infinispan Server/WildFly、HazelcastでそれぞれDockerでクラスタを構成してみる

以前、Infinispan ServerとDockerを使ってこんなエントリを書きました。

Infinispan ServerのDockerイメージを作って、クラスタを構成してみる - CLOVER

この時は、こんな感じで「--net=host」を指定して実行していました。

## Node 1
$ docker run -it --rm --net=host infinispan-server:7.2.3 -Djboss.node.name=node1

## Node 2
$ docker run -it --rm --net=host infinispan-server:7.2.3 -Djboss.socket.binding.port-offset=1000 -Djboss.node.name=node2

## Node 3
$ docker run -it --rm --net=host infinispan-server:7.2.3 -Djboss.socket.binding.port-offset=2000 -Djboss.node.name=node3

が、これをもうちょっとどうにかならないかな?ということで、調べてみました。

結論としては、できました。以降、試した順番とは逆になりますが、結果を書いていってみます。

Infinispan Server/WildFly

1番てこずったのがこれですが、なんとかなりました。

参考にしたのは、このあたり。

Wildfly cluster in docker? |JBoss Developer

3.2.8. クラスタリングの変更 - Red Hat Customer Portal

Marek Goldmann | WildFly cluster using Docker on Fedora

結論としては、以下のパラメーターで細工をすればいいみたいです。

-Djboss.bind.address=[IPアドレス]

バインドするIPアドレスを指定してねってことですと。
※「-Djboss.bind.address=」は、「-b=」でもOKです

自動的にやるには、こんな感じ。

-Djboss.bind.address=`hostname -I`

そんなわけで、Dockerfileとしてはこのように作成しました。対象は、Infinispan Serverです。
Dockerfile

FROM java:8

ENV INFINISPAN_VERSION 8.0.1.Final

RUN mkdir -p /opt/infinispan

WORKDIR /opt/infinispan

RUN wget -q http://downloads.jboss.org/infinispan/$INFINISPAN_VERSION/infinispan-server-$INFINISPAN_VERSION-bin.zip && \
    unzip infinispan-server-$INFINISPAN_VERSION-bin.zip && \
    mv infinispan-server-$INFINISPAN_VERSION infinispan-server && \
    chmod +x infinispan-server/bin/standalone.sh

RUN perl -wpi -e 's/-Xms\d+[a-z]/-Xms1g/g; s/-Xmx\d+[a-z]/-Xmx1g/g' infinispan-server/bin/standalone.conf*

EXPOSE 8080 8181 9990 11211 11222

ADD start-clustered-server.sh start-clustered-server.sh
RUN chmod a+x start-clustered-server.sh

ENTRYPOINT ["./start-clustered-server.sh"]

デフォルトのメモリが低めで、Infinispan Server 8系からどうもclustered.shがなくなったみたいなので、ちょっとヒープを広げています。

RUN perl -wpi -e 's/-Xms\d+[a-z]/-Xms1g/g; s/-Xmx\d+[a-z]/-Xmx1g/g' infinispan-server/bin/standalone.conf*

start-clustered-server.shというのは、こんな内容で書いています。
start-clustered-server.sh

#!/bin/bash

infinispan-server/bin/standalone.sh -c clustered.xml -Djboss.bind.address=`hostname -I` "$@"

これでビルドして

$ docker build -t kazuhira/infinispan-server-clustered:8.0.1 .

起動してみます。

## Node 1
$ docker run -it --rm -p 8080 -p 8181 -p 9990 -p 11211 -p 11222 kazuhira/infinispan-server-clustered:8.0.1

## Node 2
$ docker run -it --rm -p 8080 -p 8181 -p 9990 -p 11211 -p 11222 kazuhira/infinispan-server-clustered:8.0.1

起動すると、ちゃんとクラスタが構成されてくれます。

14:21:33,130 INFO  [org.infinispan.CLUSTER] (remote-thread--p2-t8) ISPN000310: Starting cluster-wide rebalance for cache default, topology CacheTopology{id=1, rebalanceId=1, currentCH=DefaultConsistentHash{ns=20, owners = (1)[2985f8e1a401: 20+0]}, pendingCH=DefaultConsistentHash{ns=20, owners = (2)[2985f8e1a401: 10+10, aa1b078b65f4: 10+10]}, unionCH=null, actualMembers=[2985f8e1a401, aa1b078b65f4]}

「-Djboss.bind.address」もしくは「-b」を指定しないと、個々のNodeが孤立してしまいます…。

あと、デフォルトで付与されていますが、「-Djava.net.preferIPv4Stack=true」も重要だと思われます。

動作確認。「11211」ポートにバインドされている、memcachedのポートを探します。

$ docker ps
CONTAINER ID        IMAGE                                        COMMAND                  CREATED             STATUS              PORTS                                                                                                                           NAMES
be79fb0b6176        kazuhira/infinispan-server-clustered:8.0.1   "./start-clustered-se"   2 minutes ago       Up 2 minutes        0.0.0.0:32832->8080/tcp, 0.0.0.0:32831->8181/tcp, 0.0.0.0:32830->9990/tcp, 0.0.0.0:32829->11211/tcp, 0.0.0.0:32828->11222/tcp   loving_banach
d633257fb4d6        kazuhira/infinispan-server-clustered:8.0.1   "./start-clustered-se"   2 minutes ago       Up 2 minutes        0.0.0.0:32827->8080/tcp, 0.0.0.0:32826->8181/tcp, 0.0.0.0:32825->9990/tcp, 0.0.0.0:32824->11211/tcp, 0.0.0.0:32823->11222/tcp   jolly_noyce

「32829」と「32824」ですね。

memcachedプロトコルで確認。

## set
$ telnet localhost 32829
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set key1 0 600 6
value1
STORED
quit
Connection closed by foreign host.

## get
$ telnet localhost 32824
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get key1
VALUE key1 0 6
value1
END
quit
Connection closed by foreign host.

OKそうですね。

一応、このDockerイメージについては、Docker Hubにpushしてあります。
https://hub.docker.com/r/kazuhira/infinispan-server-clustered/

Infinispan(Embedded Mode)

続いて、InfinispanのEmbedded Mode。

こちらは、システムプロパティ

-Djava.net.preferIPv4Stack=true

が付与されていればOKです。

こんなコードで確認しました。

設定ファイル。
infinispan.xml

<?xml version="1.0" encoding="UTF-8"?>
<infinispan
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:infinispan:config:8.0 http://www.infinispan.org/schemas/infinispan-config-8.0.xsd"
        xmlns="urn:infinispan:config:8.0">
    <jgroups>
        <stack-file name="udp" path="default-configs/default-jgroups-udp.xml"/>
    </jgroups>

    <cache-container name="cacheManager" shutdown-hook="REGISTER">
        <transport cluster="cluster" stack="udp"/>
        <jmx duplicate-domains="true"/>

        <distributed-cache name="distCache"/>
    </cache-container>
</infinispan>

ソースコード
Server.java

import org.infinispan.*;
import org.infinispan.manager.*;

public class Server {
    public static void main(String... args) throws Exception {
         EmbeddedCacheManager manager = new DefaultCacheManager("infinispan.xml");
         manager.getCache("distCache");
         System.console().readLine();
    }
}

「-Djava.net.preferIPv4Stack=true」が設定されていなかった場合は、クラスタが構成されませんでした…。

Hazelcast

めっちゃ簡単で、特に何もせずともクラスタ構成可能でした。

以下のDockerイメージを、そのまま使っても大丈夫です。

https://hub.docker.com/r/hazelcast/hazelcast/

起動。

## Node 1
$ docker run -it --rm -p 5701 hazelcast/hazelcast

## Node 2
$ docker run -it --rm -p 5701 hazelcast/hazelcast

ごく普通にクラスタが構成されます。

Members [2] {
	Member [172.17.0.60]:5701 this
	Member [172.17.0.59]:5701
}

HazelcastのDockerイメージでの起動コマンドは、こんな感じです。

echo "Process id for hazelcast instance is written to location: " $PID_FILE
$RUN_JAVA -server $JAVA_OPTS com.hazelcast.core.server.StartServer &

ごく普通に起動しているだけで、「-Djava.net.preferIPv4Stack=true」がなくてもクラスタ構成可能みたいです。

実際、自分で同じような簡単なプログラムを書いてDockerコンテナに載せて動かしても、クラスタが構成できました。

この差は、なんでしょうね…。

まあいいのですが。そういえば、Hazelcastでできるということは、PayaraでもDockerでクラスタが組めるということですね!
(ホストが異なる場合はわかりませんけど)

こちらも、動作確認。同じくmemcachedプロトコルで行います。

CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                     NAMES
423d721c1390        hazelcast/hazelcast   "/bin/sh -c 'java -cp"   29 seconds ago      Up 28 seconds       0.0.0.0:32834->5701/tcp   hungry_einstein
7795f8a855b4        hazelcast/hazelcast   "/bin/sh -c 'java -cp"   40 seconds ago      Up 39 seconds       0.0.0.0:32833->5701/tcp   elated_carson

「32834」と「32833」を使えばよさそうです。

set、get。

## set
$ telnet localhost 32834
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set key1 0 600 6
value1
STORED
quit
Connection closed by foreign host.

## get
$ telnet localhost 32833
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get key1
VALUE key1 0 6
value1
END
quit
Connection closed by foreign host.

こちらもOKそうです。