先日、Apache Geode 1.0.0-incubating.M1がリリースされました。
Apache Geode — Performance is key. Consistency is a must.
[ANNOUNCE] Apache Geode (incubating) release 1.0.0-incubating.M1
Apache Geode announces the first incubation release version 1.0.0-incubating.M1! URL
まだ1.0.0のM1という段階ではありますが、一応ディストリビューションのダウンロードなどもできるようになったので、試してみたいと思います。
Apache Geodeって?
Pivotal GemFireがOSSになったもの、という感じです。
Hello Geode: Pivotal GemFire is now open source | InfoWorld
Pivotal Releases “Geode” - The In-Memory Database Powering Pivotal GemFire | Press Release | Pivotal
Apache Geode自身のサイトは、こちら。
Apache Geode — Performance is key. Consistency is a must.
自分自身はGemFireは触ったことがないのですが、In Memory Data Gridの一種という位置づけで捉えればよさそうな感じですね。
説明としては、データを複数プロセスに跨って管理可能な、分散データ管理(主としてインメモリ)プラットフォームとなっています。
http://geode.docs.pivotal.io/docs/getting_started/geode_overview.html
主な機能は、こちらに記載があります。
http://geode.docs.pivotal.io/docs/getting_started/product_intro.html
- Peer-to-Peer、Client/Serverによる構成をとることが可能
- 分散システムに参加するメンバーを追加することで、スケール可能
- キャッシュの同期/非同期更新
- 低レイテンシによる非同期のイベント通知やメッセージ配送の保証
- JTAサポート
- クラスタの設定を、別のクラスタへ送ることができる
- HTTPによるリモート管理
- REST API
- バージョンアップ時のRolling Upgrade
といったところ。
ソースパッケージとかドキュメントをさらっと見ている限りは、えらい物量の機能が出てきそうですが、とりあえず触りはこんなところで。
ドキュメントは、以下の2箇所から見ていくことになります。
Documentation
http://geode.docs.pivotal.io/
Wiki
Index - Geode - Apache Software Foundation
ただ、これだけではちょっと足りないので、現時点ではGemFireのものも必要に応じて参照した方がよいかもしれません。
Pivotal GemFire® Documentation | Pivotal GemFire Docs
Javadoc
GemFire Java API Documentation
それでは、使っていってみることにしましょう。
インストール
ここからは、Apache Geodeのインストールと、簡単なサンプルプログラムを書いて動作確認してみたいと思います。
このあたりを参考に。
Index - Geode - Apache Software Foundation
http://geode.docs.pivotal.io/docs/getting_started/15_minute_quickstart_gfsh.html
インストールの事前条件としては、JDK 8以上とJAVA_HOMEを設定してPATHを通しておくくらいです。
http://geode.docs.pivotal.io/docs/getting_started/system_requirements/host_machine.html
http://geode.docs.pivotal.io/docs/getting_started/installation/install_standalone.html
ただ、複数ホストで使う場合は、時刻同期と名前解決に気をつけてね、と。
では、進めます。
まずは、ディストリビューションをダウンロードします。
http://geode.incubator.apache.org/releases/
今回は、「apache-geode-1.0.0-incubating.M1.tar.gz」をダウンロードしました。展開。
$ tar -zxvf apache-geode-1.0.0-incubating.M1.tar.gz
インストールは、このくらいです。
サーバー側の用意
展開したディストリビューションのbinディレクトリにある、gfshというものを起動します。
$ apache-geode-1.0.0-incubating.M1/bin/gfsh
_________________________ __
/ _____/ ______/ ______/ /____/ /
/ / __/ /___ /_____ / _____ /
/ /__/ / ____/ _____/ / / / /
/______/_/ /______/_/ /_/ v1.0.0-incubating.M1
Monitor and Manage GemFire
gfsh>
めっちゃGemFireって出ますね…。
ドキュメントに習い、LocatorとServerを開始します。
## Locatorを起動 gfsh>start locator --name=locator ## Serverを起動 gfsh>start server --name=server
この時、LocatorとServerは別プロセスで起動します。
続いて、Regionを作成します。
※ドキュメントからRegionの名前は変えていますが…
gfsh>create region --name=sampleRegion --type=REPLICATE Member | Status ------ | ------------------------------------------ server | Region "/sampleRegion" created on "server"
ここまでで、サーバー側の準備はお終いです。
クライアント側のコードを書く
それでは、ここまでに用意したサーバーを利用するアプリケーションを書いてみます。
Maven依存関係には、以下のように設定します。
※JUnitとAssertJはテストコード用です
<dependency> <groupId>org.apache.geode</groupId> <artifactId>gemfire-core</artifactId> <version>1.0.0-incubating.M1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.3.0</version> <scope>test</scope> </dependency>
artifactId、「gemfire-core」なんですね…。
import文などは、こんな感じで用意しました。
src/test/java/org/littlewings/geode/ClientServerSimpleTest.java
package org.littlewings.geode; import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.RegionDestroyedException; import com.gemstone.gemfire.cache.client.ClientCache; import com.gemstone.gemfire.cache.client.ClientCacheFactory; import com.gemstone.gemfire.cache.client.ClientRegionShortcut; import com.gemstone.gemfire.cache.client.ServerOperationException; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class ClientServerSimpleTest { // ここに、テストコードを書く! }
まずは、Getting Startedに載っているようなサンプルを記載。
@Test public void gettingStarted() { ClientCache cache = new ClientCacheFactory() .addPoolLocator("localhost", 10334) // デフォルト(localhost:10334)なら、書かなくてもOK .create(); try { Region<String, String> region = cache .<String, String>createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY) .create("sampleRegion"); region.put("key1", "value1"); assertThat(region.get("key1")) .isEqualTo("value1"); region.put("key2", "value2"); assertThat(region.get("key2")) .isEqualTo("value2"); region.remove("key2"); assertThat(region.get("key2")) .isNull(); assertThat(region.containsKey("key1")) .isTrue(); region.close(); } finally { cache.close(); } }
Regionがjava.util.ConcurrentMapを継承していて、Mapと同様な操作を行うことができます。
また、事前にRegionを作成していましたが、存在しないRegionを指定すると、Regionの操作時にエラーになるようです。
@Test public void missingRegion() { ClientCache cache = new ClientCacheFactory() .create(); try { Region<String, String> region = cache .<String, String>createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY) .create("notFoundRegion"); assertThatThrownBy(() -> region.put("key1", "value1")) .isInstanceOf(ServerOperationException.class) .hasMessageContaining("While performing a remote put") .hasCauseInstanceOf(RegionDestroyedException.class); region.close(); } finally { cache.close(); } }
環境さえ整えてしまえば、動かすこと自体はそう難しくなさそうです。
で
とまあ、Getting Startedの写しみたいな感じで進めましたが、説明を飛ばしたものがありますね。これらについて、ちょっとドキュメントを見た程度ですが書いていきます。
Locator
最初に起動したプロセスです。
http://geode.docs.pivotal.io/docs/configuring/running/running_the_locator.html
分散システムにおける、メンバーを管理するプロセスになります。このプロセスがいないと、他のプロセス(ServerやClient)がうまく動作できません。
というか、1番最初に接続しにいこうとします。
停止する場合は
※--name以外にも、--pidでPIDを指定しての停止も可能です
gfsh>stop locator --name=locator
と実行しますが、この時Serverプロセスが起動したままだと、gfshからServerを操作できなくなります…。
また、起動時に(ディレクトリを指定しなければ)カレントディレクトリに、Locator向けのディレクトリができるようです。作られるディレクトリ名は、Locatorの名前(--nameで指定した値)が反映されます。
$ ll locator/ 合計 172 drwxrwxr-x 5 xxxxx xxxxx 4096 2月 14 15:36 ./ drwxrwxr-x 6 xxxxx xxxxx 4096 2月 14 15:21 ../ drwxrwxr-x 2 xxxxx xxxxx 4096 2月 14 15:36 ConfigDiskDir_locator/ drwxrwxr-x 3 xxxxx xxxxx 4096 2月 14 15:21 GemFire_xxxxx/ drwxrwxr-x 3 xxxxx xxxxx 4096 2月 14 15:21 cluster_config/ -rw-rw-r-- 1 xxxxx xxxxx 139424 2月 14 15:36 locator.log -rw-rw-r-- 1 xxxxx xxxxx 312 2月 14 15:36 locator10334view.dat -rw-rw-r-- 1 xxxxx xxxxx 1290 2月 14 15:36 locator10334views.log -rw-rw-r-- 1 xxxxx xxxxx 5 2月 14 15:36 vf.gf.locator.pid
というわけで、Node間の通信時に必要なプロセスっぽいですね。
Client/ServerのNode Discoveryの雰囲気は、こちらのドキュメントを見ればよさそうです。
Locatorを開始する時には、たくさんのオプションが指定できるようなのです…。
gfsh>start locator --name=locator -- --bind-address --classpath --force --group --hostname-for-clients --include-system-classpath --locators --log-level --mcast-address --mcast-port --port --dir --properties-file --security-properties-file --initial-heap --max-heap --J --connect --enable-cluster-configuration --load-cluster-configuration-from-dir --cluster-config-dir
Server
続いて、Server。
http://geode.docs.pivotal.io/docs/configuring/running/running_the_cacheserver.html
こちらは、主としてデータを管理するプロセスになるようです。Regionにputしたりしたデータは、こちらが持っているようです。このため、今回書いたプログラムだとClientが終了してもデータは残りますが、Serverを再起動するとデータは失われます。
Locatorと同じく、Serverを停止する場合は以下のコマンドで。
※--name以外にも、--pidでPIDを指定しての停止も可能です
gfsh>stop server --name=server
上記コマンドで停止する場合は、Locatorが動作していないとうまくいきません。その場合は、PIDを指定して(--pid)止めるとよいでしょう。
Server側も、--nameで指定した名前でディレクトリができあがります。
$ ll server/ 合計 36 drwxrwxr-x 2 xxxxx xxxxx 4096 2月 14 15:21 ./ drwxrwxr-x 7 xxxxx xxxxx 4096 2月 14 15:38 ../ -rw-rw-r-- 1 xxxxx xxxxx 21984 2月 14 15:36 server.log -rw-rw-r-- 1 xxxxx xxxxx 5 2月 14 15:21 vf.gf.server.pid
こちらも、設定できるオプション多いですね。
gfsh>start server --name=server -- --assign-buckets --bind-address --cache-xml-file --classpath --critical-heap-percentage --critical-off-heap-percentage --dir --disable-default-server --disable-exit-when-out-of-memory --enable-time-statistics --eviction-heap-percentage --eviction-off-heap-percentage --force --group --hostname-for-clients --include-system-classpath --initial-heap --J --locators --locator-wait-time --lock-memory --log-level --max-connections --max-heap --max-message-count --max-threads --mcast-address --mcast-port --memcached-port --memcached-protocol --memcached-bind-address --redis-port --redis-bind-address --redis-password --message-time-to-live --off-heap-memory-size --properties-file --rebalance --security-properties-file --server-bind-address --server-port --socket-buffer-size --spring-xml-location --statistic-archive-file --use-cluster-configuration
Region
Apache Geodeのコアブロック、だそうで。
http://geode.docs.pivotal.io/docs/basic_config/data_regions/chapter_overview.html#data_regions
キャッシュに登録されたデータを持ち、put/get/queryなどの各種操作を実行することができます。
Regionの種類はReplicated、Partitionedなどたくさんありますが
http://geode.docs.pivotal.io/docs/developing/region_options/region_types.html
今回は、REPLICATEをRegion Shortcutを使って指定しました。
http://geode.docs.pivotal.io/docs/reference/topics/region_shortcuts_table.html
本来なら、データを全Nodeに持つタイプの設定ですが、今回はServerが1Nodeしかいないのであんまり関係ないですけどね…。
ちなみに、他のIn Memory Data GridだとApache GeodeでいうRegionがCacheなどの名前になっていたり、CacheがCacheManagerとかの名前になっていたりするイメージがあったので、最初戸惑いました…。
まとめ
というわけで、Apache Geodeをさらっとですが使って、ここまでの説明を簡単に書いてみました。
なかなか機能が多そうなのと、慣れるまで時間がかかりそうな気がするのですが…マイペースに見ていこうかなと。
あと、まだ1.0.0-incubating.M1という段階なので、今後もけっこう変わるんだろうなぁと思いつつ。早く1.0.0がリリースされるといいなぁと思います。