Payara Microで、「--hzConfigFile」という起動オプションを使用することで、Hazelcastの設定ファイルを与えることができるようです。
なんとなくオプションが追加されていたのは気付いていましたが、これが使えるようになったのはPayara 4.1.153からっぽいですね。
Payara Micro Command Line Options
Payara 4.1.153以前はPayara MicroではHazelcastの設定に付いては、マルチキャストアドレス/ポート、コミュニケーションポートの開始ポート、そもそもクラスタを無効化するくらいが指定できたようですが、設定ファイルが使えるとだいぶ設定の幅が広がりますね。
せっかくなので、ちょっと試してみました。
準備
まずは、動作対象となるアプリケーションを作ってみます。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.littlewings</groupId> <artifactId>payara-micro-hazelcast-configuration</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <build> <finalName>app</finalName> </build> <dependencies> <dependency> <groupId>fish.payara.extras</groupId> <artifactId>payara-micro</artifactId> <version>4.1.1.162</version> <scope>provided</scope> </dependency> </dependencies> </project>
アプリケーションとしては、HttpSessionを使った簡単なJAX-RS APIを用意します。
src/main/java/org/littlewings/payara/rest/JaxrsApplication.java
package org.littlewings.payara.rest; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("rest") public class JaxrsApplication extends Application { }
src/main/java/org/littlewings/payara/rest/HelloWorldResource.java
package org.littlewings.payara.rest; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; @Path("helloworld") public class HelloWorldResource { @GET @Produces(MediaType.TEXT_PLAIN) public String helloWorld(@Context HttpServletRequest request) { HttpSession session = request.getSession(); String time = (String) session.getAttribute("time"); if (time == null) { LocalDateTime now = LocalDateTime.now(); time = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); session.setAttribute("time", time); } return time; } }
web.xmlには、distributableを付けておきます。
src/main/webapp/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_3_1.xsd" version="3.1"> <distributable/> </web-app>
で、アプリケーションをビルドしておきます。
$ mvn package
以降、このアプリケーションを起動する時に、Payara MicroにデプロイしつつHazelcastの設定を変えていってみます。
今回利用するPayara MicroのJARファイルは、payara-micro-4.1.1.162.jarとなります。
Payara Server & Payara Micro - Downloads
また、今回はPayara Microで起動するアプリケーションは、Node 2つでクラスタを組むものとします。2つ目のNodeのHTTPリッスンポートは、9080とします。
起動時には、以下のコマンドで実行することを前提とします。以降では、以下のコマンドの[Hazelcastの設定ファイル]の部分に該当するファイルを作成、指定して実行していきます。
## Node 1 $ java -jar payara-micro-4.1.1.162.jar --deploy target/app.war --hzConfigFile [Hazelcastの設定ファイル] ## Node 2 $ java -jar ../payara-micro-4.1.1.162.jar --deploy target/app.war --port 9080 --hzConfigFile [Hazelcastの設定ファイル]
HttpSessionが共有されているかどうかの動作確認には、以下のコマンドを使っています。
## Node 1 $ curl -b cookie.txt -c cookie.txt http://localhost:8080/app/rest/helloworld 2016-06-18 21:18:28 ## Node 2 $ curl -b cookie.txt -c cookie.txt http://localhost:9080/app/rest/helloworld 2016-06-18 21:18:28
HttpSessionが共有されていれば、同じ日時が返ってきます、と。
グループ名を変えてみる
まず、設定ファイルの内容が反映されているか確認するために、グループ名を変えてみることにします。ここでいうグループ名とは、Hazelcastがクラスタを構成するためのグループで、Hazelcastクラスタはひとつのグループに属することになります。
最初は、設定なしの状態で起動してみましょう。
$ java -jar payara-micro-4.1.1.162.jar --deploy target/app.war
起動時に、Hazelcastクラスタに属するメンバーが以下のように出力されます。
[2016-06-18T20:27:17.624+0900] [Payara Micro 4.1] [INFO] [] [com.hazelcast.cluster.impl.MulticastJoiner] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1466249237624] [levelValue: 800] [[ [172.17.0.1]:5900 [development] [3.6.2] Members [1] { Member [172.17.0.1]:5900 this } ]]
ここで、次のような設定ファイルを用意します。groupタグの中が、グループの設定です。クラスタグループ名は、「my-cluster」にしました。
注)マルチキャスト有効化の設定が入っていますが、これを書かないとクラスタ構成自体も無効化されてしまうようなので、設定ファイルを与える場合は明示する必要があるようです
hazelcast-custom-group.xml
<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <group> <name>my-cluster</name> <password>password</password> </group> <network> <join> <multicast enabled="true"/> </join> </network> </hazelcast>
では、起動してみます。
$ java -jar ../payara-micro-4.1.1.162.jar --deploy target/app.war --hzConfigFile hazelcast-custom-group.xml
起動時に認識したメンバーの出力が、以下のようになりました。
[2016-06-18T20:34:14.325+0900] [Payara Micro 4.1] [INFO] [] [com.hazelcast.cluster.impl.MulticastJoiner] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1466249654325] [levelValue: 800] [[ [172.17.0.1]:5701 [my-cluster] [3.6.2] Members [1] { Member [172.17.0.1]:5701 this } ]]
※コミュニケーションポートの設定がHazelcastのデフォルトに戻っているので、5701に…
ちゃんと「my-cluster」になっていますね。
[172.17.0.1]:5701 [my-cluster] [3.6.2]
続いて、他の設定も変えていってみましょう。
マルチキャストを無効化する
(デフォルトの)Hazelcastはマルチキャストを使ってクラスタを構成しますが(Node Discovery)、開発環境等でこれを無効化するには、ネットワーク設定でマルチキャストを使わないようにします。
hazelcast-disable-mc.xml
<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <network> <join> <multicast enabled="false"/> </join> </network> </hazelcast>
これで、スタンドアロンになります。
まあ、Payara Microの場合はHazelcastの設定ファイルを与えてしまうと、マルチキャストを明示的に有効化しないとスタンドアロンになるみたいですが…。
ちなみに、単にクラスタを無効化したいのであれば、Hazelcastの設定ファイルを与えずとも「--noCluster」を使えばOKです。起動もちょこっと速くなりますね。
$ java -jar ../payara-micro-4.1.1.162.jar --deploy target/app.war --noCluster
この方法でもクラスタは構成しなくなります。
TCPでクラスタを構成する
Payara Micro+Hazelcastのデフォルトのクラスタ構成(Node Discovery)はマルチキャストですが、これをTCPに変更してみます。
設定ファイルの例は、以下のとおり。
hazelcast-enable-tcp.xml
<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <network> <port auto-increment="true">6000</port> <join> <multicast enabled="false"/> <tcp-ip enabled="true"> <member>localhost</member> </tcp-ip> </join> </network> </hazelcast>
今回はわかりやすいように、コミュニケーションポートも6000に変えてみました(Payara Microのデフォルトだと5900)。また、localhostの範囲でクラスタを作るようにしています。
[2016-06-18T20:43:26.613+0900] [Payara Micro 4.1] [INFO] [] [com.hazelcast.cluster.ClusterService] [tid: _ThreadID=47 _ThreadName=hz._hzInstance_1_dev.generic-operation.thread-0] [timeMillis: 1466250206613] [levelValue: 800] [[ [localhost]:6000 [dev] [3.6.2] Members [2] { Member [localhost]:6000 this Member [localhost]:6001 } ]]
Mapの設定をしてみる
続いて、Payara MicroがHttpSessionのデータ保存に利用する、Distributed Mapの設定をしてみましょう。
今回は、Distributed Map名「/app」に対して、いろいろ設定してみました。
hazelcast-custom-map.xml
<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <network> <join> <multicast enabled="true"/> </join> </network> <map name="/app"> <in-memory-format>BINARY</in-memory-format> <backup-count>0</backup-count> <async-backup-count>1</async-backup-count> <near-cache name="default"> <in-memory-format>BINARY</in-memory-format> <max-size>100</max-size> <time-to-live-seconds>600</time-to-live-seconds> <max-idle-seconds>60</max-idle-seconds> <invalidate-on-change>true</invalidate-on-change> <cache-local-entries>false</cache-local-entries> </near-cache> </map> </hazelcast>
ムダにNear Cacheを使ってみたり、バックアップは非同期で作成するような設定にしています。
なんで名前が「/app」かなのですが、WARファイル名前というか、コンテキストパスに依存しています?
今回のWARファイルの名前は、「app.war」です。
※pom.xmlより
<build> <finalName>app</finalName> </build>
なお、「default」という特殊な名前のDistributed Mapの設定を行うと、他に作成されるDistributed Mapにも設定が引き継がれるので注意しておきましょう。
<map name="default">
明示的に名前を付けて設定を定義した場合は、「default」には引きずられないようです。
Mananagement Centerを使う
最後は、Hazelcastが提供するManagement Centerと接続するように設定してみましょう。
このManagement Centerを使うと、Hazelcastクラスタのモニタリングができるようになります。
※Payara自体がどの程度Hazelcastの状態を見れるかはわかっていません、スミマセン…
Management Centerを使うには、まずHazelcastのダウンロードページよりHazelcastのディストリビューションをダウンロードしてくる必要があります。
今回は、Payaraが依存しているHazelcast 3.6.2のtar.gzファイルをダウンロードしました。
展開。
$ tar -zxvf hazelcast-3.6.2.tar.gz ll hazelcast-3.6.2/mancenter 合計 34924 drwxr-xr-x 2 xxxxx xxxxx 4096 6月 18 19:51 ./ drwxr-xr-x 9 xxxxx xxxxx 4096 6月 18 19:51 ../ -rw-r--r-- 1 xxxxx xxxxx 35743282 6月 18 19:51 mancenter-3.6.2.war -rw-r--r-- 1 xxxxx xxxxx 453 6月 18 19:51 startManCenter.bat -rw-r--r-- 1 xxxxx xxxxx 306 6月 18 19:51 startManCenter.sh
このManagement Center、単独でも実行可能WARとして起動できるのですが、今回はこれもPayara Microにデプロイしてみます。
クラスタを構成する必要はないので、「--noCluster」を付与します。また、HTTPリッスンポートは20000とします。
$ java -jar payara-micro-4.1.1.162.jar --deploy hazelcast-3.6.2/mancenter/mancenter-3.6.2.war --noCluster --port 20000
この設定で、「http://localhost:20000/mancenter-3.6.2」にアクセスすると以下のような画面が表示されます。
デフォルトだと、そのまま「login」でログインできます。
まだクラスタから情報が届いていないので、Hazelcastクラスタに関する情報はありません。
それでは、アプリケーション側のHazelcastの設定を行います。
hazelcast-mancenter.xml
<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <network> <join> <multicast enabled="true"/> </join> </network> <management-center enabled="true" update-interval="3">http://localhost:20000/mancenter-3.6.2</management-center> </hazelcast>
「management-center」タグを使うことで、Management Centerへの接続設定を行うことができます。
今回は、「http://localhost:20000/mancenter-3.6.2」へ3秒に1度情報を更新する設定になっています。
Distributed Mapなどの設定は、デフォルトです。
ここで、2 Node起動してみます。すると、Management Centerの方でHazelcastクラスタを検知しているのでManagement Centerの開いているブラウザをリロードします。
ここで、このまま「Connect」ボタンを押すと、Hazelcastクラスタの情報が参照できます。
「/app」というMapsへのリンクがあるので、こちらを見てみます。
その後でcurlでアプリケーションに対してアクセスしてみます。
## to Node 1 curl -b cookie.txt -c cookie.txt http://localhost:8080/app/rest/helloworld ## to Node 2 curl -b cookie.txt -c cookie.txt http://localhost:9080/app/rest/helloworld
とまあ、こんな感じにPayara Microが使っているHttpSession(Distributed Map)の情報が見れました、と。
まとめ
Payara Microで起動するアプリケーションに対して、Hazelcastの設定ファイルを与えていくつか挙動を変えてみました。
Management CenterなどはちょっとHazelcastの製品寄りの話な気もしますが…あと、Payara自体の管理機能は見ていませんが…。
まあ、Payara Microを使ってもある程度Hazelcastの設定を制御できそうなことがわかってよかったです。