CLOVER🍀

That was when it all began.

Infinispan ServerをJGroups Gossip Routerでクラスタリングする

Infinispanでクラスタを構成する際のNode Discoveryの方法のひとつとして、JGroupsのGossip Routerを使ってみます。

GossipRouter

こちらを使うことで、クラスタに参加するNodeを探索するNode Discoveryの仕組みを、Gossip Routerで行うことができます。

Gossip Routerとは?

Gossip Routerについては、こちらに記載があります。

JGroupsGossipRouter |JBoss Developer

もともとは、クラスタにいるNodeがファイアーウォールがあるなど事情で、直接Node間で接続できない場合に利用するようです。
その代替として、各NodeはGossip Routerとさえ通信できればよい、という感じみたいです。

Gossip Routerそのものは、クラスタを構成するNodeとは別の、単独のプロセスです。JGroupsのJARの中に含まれています。

この目的の場合、TUNNELプロトコルを使用して、Gossip Router越しにNode間のやり取りをするようです。
通信自体には、TCPを使用するようですね。

TUNNEL

で、これはクラスタ内の通信に制限がある場合に、どうにかするためにGossip Routerを使用するようなのですが、
Node Discovertyだけでも使用することができます。

これが、TCPGOSSIPです。

TCPGOSSIP

Node Discoveryでは、マルチキャストを使ったPINGTCPでの接続先を並べるTCPPINGなどがありますが、TCPGOSSIPの場合はGossip Routerへの
接続先を並べることになります(initial_hosts)。

あとは、接続タイムアウトや再接続の間隔などを設定することができます。

クラウド環境ではマルチキャストが使えないものが多いので、それ以外の手段でNode Discoveryを行う必要がありますが、
その選択肢のひとつとして上がっています。

GossipRouter

ところで、利用するGossip Routerはinitial_hostsで指定するのですが、初期の接続先というより、実行時にそれ以上増やせないですよね…?
実際に使う時には、複数のGossip Routerを使用して、プロセスダウンとかに備えるのかなぁと思います。

Gossip Routerを使って、Infinispan Serverでクラスタを構成してみる

それでは、Gossip Routerを使ってInfinispan Serverのクラスタを構成してみましょう。

Javaバージョンは、こちら。

$ java -version
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-8u171-b11-0ubuntu0.18.04.1-b11)
OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)

JGroupsは4.0.13を使い、Infinispan Serverは9.3.1.Finalを使用します。

クラスタに参加するNodeや、Gossip Routerの情報は以下の通り。

  • Gossip Router … 3つ(172.17.0.2〜4)
  • Infinispan Server … 3 Node(172.17.0.5〜7) ※ホスト名は、infinispan1〜3としました

準備

まず、JGroupsをダウンロードしてきて、Gossip Routerを起動します。「org.jgroups.stack.GossipRouter」を指定して起動してあげれば、OKです。

## Gossip Router 1
$ wget https://search.maven.org/remotecontent?filepath=org/jgroups/jgroups/4.0.13.Final/jgroups-4.0.13.Final.jar -O jgroups.jar
$ java -cp jgroups.jar org.jgroups.stack.GossipRouter


## Gossip Router 2
$ wget https://search.maven.org/remotecontent?filepath=org/jgroups/jgroups/4.0.13.Final/jgroups-4.0.13.Final.jar -O jgroups.jar
$ java -cp jgroups.jar org.jgroups.stack.GossipRouter


## Gossip Router 3
$ wget https://search.maven.org/remotecontent?filepath=org/jgroups/jgroups/4.0.13.Final/jgroups-4.0.13.Final.jar -O jgroups.jar
$ java -cp jgroups.jar org.jgroups.stack.GossipRouter

Gossip Routerの起動引数は今回指定しませんが、起動クラスであるGossipRouterクラスのフィールドは、起動引数でいろいろ設定することができます。

http://www.jgroups.org/javadoc4/org/jgroups/stack/GossipRouter.html

オプションの指定方法は、ソースコードを参照することになるでしょう。
https://github.com/belaban/JGroups/blob/JGroups-4.0.13.Final/src/org/jgroups/stack/GossipRouter.java#L545-L589

ログ出力などは特にしていませんが、Docker HubにあるGossip RouterはApache Log4j2を使ってログ出力するように設定されているので、こちらを
参考にしてもよいでしょう。

JGroups Gossip Router Docker Image

Infinispan Serverは、各Nodeでzipファイルを展開しておきます。

$ unzip infinispan-server-9.3.1.Final.zip
$ cd infinispan-server-9.3.1.Final

起動

では、Infinispan ServerをGossip Routerを使うようにして起動してみましょう。

クラスタ構成とすることができる設定ファイル、「clustered.xml」にはすでにGossip Routerを使う設定が含まれています。
https://github.com/infinispan/infinispan/blob/9.3.1.Final/server/integration/jgroups/src/main/resources/subsystem-templates/infinispan-jgroups.xml#L45-L63

他にUDPTCPもありますが、これがデフォルトで「udp」stackを選択するようになっています。
https://github.com/infinispan/infinispan/blob/9.3.1.Final/server/integration/jgroups/src/main/resources/subsystem-templates/infinispan-jgroups.xml#L10

これは、システムプロパティ「jboss.default.jgroups.stack」で「tcp-gossip」を指定することで、stackを切り替えることができます。

また、TCPGOSSIPの場合は「initial_hosts」を指定する必要がありますが、これはシステムプロパティ「groups.gossip.initial_hosts」で指定することができます。
https://github.com/infinispan/infinispan/blob/9.3.1.Final/server/integration/jgroups/src/main/resources/subsystem-templates/infinispan-jgroups.xml#L48

「initial_hosts」の書式は、以下の通りです。

## 単数
host[port]

## 複数
host[port],host[port],host[port]

以上を踏まえると、各Infinispan Serverの起動引数は、以下のようになります。

## Node 1
$ bin/standalone.sh -c clustered.xml -Djboss.bind.address=172.17.0.5 -Djboss.default.jgroups.stack=tcp-gossip -Djgroups.gossip.initial_hosts=172.17.0.2[12001],172.17.0.3[12001],172.17.0.4[12001]


## Node 2
$ bin/standalone.sh -c clustered.xml -Djboss.bind.address=172.17.0.6 -Djboss.default.jgroups.stack=tcp-gossip -Djgroups.gossip.initial_hosts=172.17.0.2[12001],172.17.0.3[12001],172.17.0.4[12001]


## Node 3
$ bin/standalone.sh -c clustered.xml -Djboss.bind.address=172.17.0.7 -Djboss.default.jgroups.stack=tcp-gossip -Djgroups.gossip.initial_hosts=172.17.0.2[12001],172.17.0.3[12001],172.17.0.4[12001]

これで、クラスタが構成されます。

2018-08-05 10:00:14,884 INFO  [org.infinispan.CLUSTER] (jgroups-11,infinispan1) ISPN000094: Received new cluster view for channel cluster: [infinispan1|2] (3) [infinispan1, infinispan2, infinispan3]

ispn-cliで確認する場合。

$ bin/ispn-cli.sh -c
[standalone@localhost:9990 /] /subsystem=datagrid-infinispan/cache-container=clustered:read-attribute(name=members)
{
    "outcome" => "success",
    "result" => "[infinispan1, infinispan2, infinispan3]"
}

1度クラスタが構成された後は、Gossip RouterがダウンしていてもNodeがクラスタから離脱することはありません(もちろん、Node本体が落ちたりしたら
別ですが)。

また、「initial_hosts」で指定したGossip Routerは、すべてが接続可能である必要はなく、どれかが起動していれば機能してくれます。「initial_hosts」に
列挙されていても起動していないGossip Routerがあっても、あとで起動すれば検出してくれます。

例えば、クラスタ構成 → Gossip Router全ダウン → クラスタにNode追加(Gossip Routerがないのでクラスタ参加できず) → Gossip Router復旧…という
ステップを踏むと、あとで追加したNodeもしばらくするとGossip Routerを検出してクラスタに参加してくれます。

Embedded Modeの場合

Embedded Mode用のデフォルトのTCPGOSSIP用の設定ファイルは作成されていませんが、TCP用のものを参考に、MPINGの部分をTCPGOSSIPに変更したものを
作成すればよいと思います。
https://github.com/infinispan/infinispan/blob/9.3.1.Final/core/src/main/resources/default-configs/default-jgroups-tcp.xml