CLOVER🍀

That was when it all began.

Apache GeodeをPeer-to-Peer(Standalone)で使う

この間、Apache GeodeをClient/Server構成でGetting Started的なことをやったので、今度はPeer-to-Peer構成で試してみたいと思います。
※諸事情で、Client/Serverから1度方向転換したい…

といっても、今回はまだクラスタ構成にチャレンジしません(なのでタイトルがStandalone)。

利用するApache Geodeバージョンは、1.0.0-incubating.M1とします。

始めるにあたり、Peer-to-PeerのGetting Started的なドキュメントってそうない感じだったので、とっかかりはちょっと戸惑いましたね…。

ここを見たらいいのかな。

http://geode.docs.pivotal.io/docs/basic_config/the_cache/managing_a_peer_server_cache.html

準備

まずはMaven依存関係。

        <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>

Geodeと、テストコードを使うのでJUnitとAssertJを含めています。

はじめてのPeer-to-Peer構成

さっきからPeer-to-Peerと書いていますが、要は同一JavaVM内でGeodeを使う構成のことと考えるとよいと思います。

まずコードの雛形ですが、以下のようなものを用意しました。
src/test/java/org/littlewings/geode/PeerToPeerSimpleTest.java

package org.littlewings.geode;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionShortcut;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class PeerToPeerSimpleTest {
    // ここに、テストコードを書く
}

import文は、こちらのものが入っているものとします。

で、最初に書いたコード。

    @Test
    public void gettingStarted() {
        Cache cache =
                new CacheFactory()
                        .create();

        Region<String, String> region =
                cache
                        .<String, String>createRegionFactory(RegionShortcut.PARTITION)
                        .create("sampleRegion");

        region.put("key1", "value1");
        assertThat(region.get("key1"))
                .isEqualTo("value1");

        region.put("key2", "value2");
        assertThat(region.get("key2"))
                .isEqualTo("value2");

        assertThat(region)
                .hasSize(2);

        region.remove("key2");
        assertThat(region.get("key2"))
                .isNull();

        region.close();
        cache.close();
    }

今回は、CacheFactoryというクラスからCacheを取得します。Client/Server構成の時は、ClientCacheFactoryでした。

        Cache cache =
                new CacheFactory()
                        .create();

取得したCacheから、Regionを作成します。

        Region<String, String> region =
                cache
                        .<String, String>createRegionFactory(RegionShortcut.PARTITION)
                        .create("sampleRegion");

あとはClient/Serverと同じように、Regionに対して操作していきます。
※Regionインターフェースは、java.util.concurrent.ConcurrentMapを拡張しています

RegionFactory#createしなかった場合は?

CacheからRegionFactoryを作成せずに、いきなりCache#getResionを行った場合は返ってくるRegionがnullになります。

    @Test
    public void missingRegion() {
        Cache cache =
                new CacheFactory()
                        .create();

        Region<String, String> region =
                cache.getRegion("sampleRegion");

        assertThat(region)
                .isNull();

        region =
                cache
                        .<String, String>createRegionFactory(RegionShortcut.PARTITION)
                        .create("sampleRegion");

        region.put("key1", "value1");
        assertThat(region.get("key1", "value1"))
                .isEqualTo("value1");

        region.close();
        cache.close();
    }

ですので、Regionはちゃんと作成しましょう、と。

        region =
                cache
                        .<String, String>createRegionFactory(RegionShortcut.PARTITION)
                        .create("sampleRegion");

構成済みのRegionを取得する

ここまでの例は、RegionFactoryおよびRegionをプログラム側で作成していましたが、設定ファイルで定義済みのものを取得する事もできるようです。

http://geode.docs.pivotal.io/docs/basic_config/data_regions/create_a_region_with_cacheXML.html

サンプルはこちら。

    @Test
    public void configuredRegion() {
        Cache cache =
                new CacheFactory()
                        .set("cache-xml-file", "cache-spec.xml")
                        .create();

        Region<String, String> region =
                cache.getRegion("sampleRegion");

        assertThat(region)
                .isNotNull();

        region.put("key1", "value1");
        assertThat(region.get("key1"))
                .isEqualTo("value1");

        region.close();
        cache.close();
    }

CacheFactory#setで設定をしていますが、こちらにはgemfire.propertiesで設定できる内容が指定できるそうです。

http://geode.docs.pivotal.io/docs/reference/topics/gemfire_properties.html

CacheFactory (GemFire Java API Documentation)

「cache-xml-file」のデフォルト値は「cache.xml」らしいのですが、今回は明示的にずらしてみました。

用意した設定ファイルは、こちらです。
src/test/resources/cache-spec.xml

<?xml version="1.0" encoding="UTF-8"?>
<cache
        xmlns="http://schema.pivotal.io/gemfire/cache"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache http://schema.pivotal.io/gemfire/cache/cache-8.1.xsd"
        version="8.1">
    <region name="sampleRegion" refid="PARTITION"/>
</cache>

XML Schemaで指定するバージョンは、今のところ8.1でOK?アーティファクト内には、8.1と9.0がありましたが、ドキュメントは8.1なのでとりあえず合わせておきました。

http://geode.docs.pivotal.io/docs/reference/topics/elements_ref.html

まとめ

Apache Geodeで、Peer-to-Peer構成(といってもStandaloneですが)で動かしてみました。

けっこう苦労するのかな?と思いましたが、ここまではあっさりでした。あとは、クラスタが組めれば…。