Merge pull request #64 from dihardman/feature/GEODE-5414
GEODE-5414: Adding WAN example
diff --git a/build.gradle b/build.gradle
index e8e1db6..525b37e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -75,8 +75,14 @@
task cleanServer {
doLast {
delete 'locator'
+ delete 'locator-ln'
+ delete 'locator-ny'
delete 'server1'
delete 'server2'
+ delete 'server-ln-1'
+ delete 'server-ln-2'
+ delete 'server-ny-1'
+ delete 'server-ny-2'
}
}
clean.finalizedBy cleanServer
diff --git a/gradle/rat.gradle b/gradle/rat.gradle
index 63e8d7b..bc0c2ab 100644
--- a/gradle/rat.gradle
+++ b/gradle/rat.gradle
@@ -64,7 +64,13 @@
// working directories
'**/locator/**',
'**/server1/**',
- '**/server2/**'
+ '**/server2/**',
+ '**/locator-ln/**',
+ '**/server-ln-1/**',
+ '**/server-ln-2/**',
+ '**/locator-ny/**',
+ '**/server-ny-1/**',
+ '**/server-ny-2/**'
]
}
diff --git a/settings.gradle b/settings.gradle
index d5857ee..c283d8c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -35,3 +35,4 @@
include 'expiration'
include 'indexes'
include 'transaction'
+include 'wan'
diff --git a/wan/README.md b/wan/README.md
new file mode 100644
index 0000000..3b05717
--- /dev/null
+++ b/wan/README.md
@@ -0,0 +1,125 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Geode WAN replication example
+
+This example demonstrates Geode support for asynchronous WAN
+replication between clusters. WAN replication allows remote Geode
+clusters to automatically keep their region data consistent through
+the use of gateway senders and receivers. A gateway sender distributes
+region events to another, remote Geode cluster. A gateway receiver
+configures a physical connection for receiving region events from
+gateway senders in remote Geode clusters. The gateway senders and
+receivers can be configured in several different topologies based on
+specific business needs. For more information on example topologies
+and associated use cases see Geode documentation on
+[Multi-site WAN Configuration](http://geode.apache.org/docs/guide/topologies_and_comm/multi_site_configuration/chapter_overview.html)
+
+In this example, two clusters are created on your local machine, each
+with a unique distributed system id and the WAN gateway configured
+for active-active, bidirectional region updates. The New York cluster (ny)
+has id=1 and the London cluster (ln) has id=2. Each cluster contains the same
+partitioned region (example-region) and each has parallel gateway senders,
+which means each server in the cluster will send data updates for
+the primary region buckets they hold. Alternately, you can configure
+serial gateway senders, where only one server in each cluster sends all data
+updates across the WAN. Serial gateway senders are typically used for
+replicated regions or when the order of events between different keys in
+a partitioned region needs to be preserved.
+
+This example runs a single client that connects to the London cluster and
+puts 10 entries into the example-region and prints them. After the client
+app has run, both clusters will contain the data.
+
+**Special Note**
+The gfsh scripts and gradle tasks for this example do not follow the standard
+used by other geode-examples in order to create 2 separate clusters. Due to
+this, you must follow the steps outlined below, as this example will not
+run using the runAll gradle task.
+
+This example assumes that Java and Geode are installed.
+
+## Steps
+
+1. From the `geode-examples/wan` directory, build the client app example
+
+ $ ../gradlew build
+
+2. Run the script that starts the London cluster (1 locator and 2 servers) and
+ creates the gateway senders and receivers.
+
+ $ gfsh run --file=scripts/start-ln.gfsh
+
+3. Run the script that starts the New York cluster (1 locator and 2 servers) and
+ creates the gateway senders and receivers.
+
+ $ gfsh run --file=scripts/start-ny.gfsh
+
+4. Run the script that creates the example-region in each cluster and associates the
+ gateway senders to this region.
+
+ $ gfsh run --file=scripts/start-wan.gfsh
+
+5. Run the client example app that connects to the London cluster and puts 10 entries
+into the `example-region`. The data will be automatically sent to the New York cluster,
+as well as printed to the console.
+
+ $ ../gradlew run
+
+6. In one terminal, run a `gfsh` command, connect to the New York cluster, and verify
+ the region contents
+
+ $ gfsh
+ ...
+ Cluster-1 gfsh>connect --locator=localhost[10331]
+ Cluster-1 gfsh>query --query="select e.key from /example-region.entries e"
+ ...
+
+7. In another terminal, run a `gfsh` command, connect to the London cluster, and verify
+ the region contents
+
+ $ gfsh
+ ...
+ Cluster-2 gfsh>connect --locator=localhost[10332]
+ Cluster-2 gfsh>query --query="select e.key from /example-region.entries e"
+ ...
+
+8. Use other gfsh commands to learn statistics about the regions, gateway senders,
+ and gateway receivers for each cluster.
+
+ Cluster-1 gfsh>describe region --name=example-region
+ Cluster-1 gfsh>list gateways
+
+9. In the terminal connected to the New York cluster, put another entry in the region
+ and verify it is in the region on this cluster.
+
+ Cluster-1 gfsh>put --key=20 --value="value20" --region=example-region
+ Cluster-1 gfsh>query --query="select e.key from /example-region.entries e"
+
+10. In the terminal connected to the London cluster, verify the new entry has also
+ been added to the region on this cluster.
+
+ Cluster-2 gfsh>query --query="select e.key from /example-region.entries e"
+
+11. Exit gfsh in each terminal and shutdown the cluster using the stop.gfsh script
+
+ $ gfsh run --file=scripts/stop.gfsh
+
+12. Clean up any generated directories and files.
+
+ $ ../gradlew cleanServer
+
diff --git a/wan/scripts/start-ln.gfsh b/wan/scripts/start-ln.gfsh
new file mode 100644
index 0000000..59ce76f
--- /dev/null
+++ b/wan/scripts/start-ln.gfsh
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Start locator for London (ln) cluster
+start locator --name=locator-ln --port=10332 --locators=localhost[10332] --mcast-port=0 --log-level=config \
+ --J=-Dgemfire.remote-locators=localhost[10331] --J=-Dgemfire.distributed-system-id=2 \
+ --J=-Dgemfire.jmx-manager-start=true --J=-Dgemfire.jmx-manager-http-port=8082 \
+ --J=-Dgemfire.jmx-manager-port=1092
+
+start server --name=server-ln-1 --locators=localhost[10332] --mcast-port=0 --log-level=config \
+ --enable-time-statistics=true --statistic-archive-file=cacheserver.gfs --server-port=0 \
+ --classpath=../build/classes/main --J=-Dgemfire.statistic-sampling-enabled=true \
+ --J=-Dgemfire.distributed-system-id=2 --J=-Dgemfire.conserve-sockets=false \
+ --J=-Dgemfire.log-file=cacheserver.log
+
+start server --name=server-ln-2 --locators=localhost[10332] --mcast-port=0 --log-level=config \
+ --enable-time-statistics=true --statistic-archive-file=cacheserver.gfs --server-port=0 \
+ --classpath=../build/classes/main --J=-Dgemfire.statistic-sampling-enabled=true \
+ --J=-Dgemfire.distributed-system-id=2 --J=-Dgemfire.conserve-sockets=false \
+ --J=-Dgemfire.log-file=cacheserver.log
+
+# Create gateway receivers for all servers in the London site
+create gateway-receiver
+
+# Create gateway senders to send updates to the New York site
+create gateway-sender --id="ny" --parallel="true" --remote-distributed-system-id="1"
+
+list members
+
diff --git a/wan/scripts/start-ny.gfsh b/wan/scripts/start-ny.gfsh
new file mode 100644
index 0000000..5b8e9e8
--- /dev/null
+++ b/wan/scripts/start-ny.gfsh
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Start locator for New York (ny) cluster
+start locator --name=locator-ny --port=10331 --locators=localhost[10331] --mcast-port=0 --log-level=config \
+ --J=-Dgemfire.remote-locators=localhost[10332] --J=-Dgemfire.distributed-system-id=1 \
+ --J=-Dgemfire.jmx-manager-start=true --J=-Dgemfire.jmx-manager-http-port=8081 \
+ --J=-Dgemfire.jmx-manager-port=1091
+
+start server --name=server-ny-1 --locators=localhost[10331] --mcast-port=0 --log-level=config \
+ --enable-time-statistics=true --statistic-archive-file=cacheserver.gfs --server-port=0 \
+ --classpath=../build/classes/main --J=-Dgemfire.statistic-sampling-enabled=true \
+ --J=-Dgemfire.distributed-system-id=1 --J=-Dgemfire.conserve-sockets=false \
+ --J=-Dgemfire.log-file=cacheserver.log
+
+start server --name=server-ny-2 --locators=localhost[10331] --mcast-port=0 --log-level=config \
+ --enable-time-statistics=true --statistic-archive-file=cacheserver.gfs --server-port=0 \
+ --classpath=../build/classes/main --J=-Dgemfire.statistic-sampling-enabled=true \
+ --J=-Dgemfire.distributed-system-id=1 --J=-Dgemfire.conserve-sockets=false \
+ --J=-Dgemfire.log-file=cacheserver.log
+
+# Create gateway receivers for all servers in the New York cluster
+create gateway-receiver
+
+# Create gateway senders for servers to send updates to the London site
+create gateway-sender --id="ln" --parallel="true" --remote-distributed-system-id="2"
+
+list members
+
diff --git a/wan/scripts/start-wan.gfsh b/wan/scripts/start-wan.gfsh
new file mode 100644
index 0000000..abdfc3f
--- /dev/null
+++ b/wan/scripts/start-wan.gfsh
@@ -0,0 +1,38 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Connect to New York site and create gateway sender
+connect --locator=localhost[10331]
+
+# Create the region that will share data with the London site
+create region --name=example-region --type=PARTITION_REDUNDANT --gateway-sender-id="ln"
+
+# Check the status of the London site
+list members
+describe region --name=example-region
+
+# Disconnect from New York site and connect to London site
+disconnect
+connect --locator=localhost[10332]
+
+# Create the region that will share data with the New York site
+create region --name=example-region --type=PARTITION_REDUNDANT --gateway-sender-id="ny"
+
+# Check the status of the London site
+list members
+describe region --name=example-region
+
diff --git a/wan/scripts/start.gfsh b/wan/scripts/start.gfsh
new file mode 100644
index 0000000..4468968
--- /dev/null
+++ b/wan/scripts/start.gfsh
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Start the London (ln) cluster
+run --file=./scripts/start-ln.gfsh
+list members
+disconnect
+
+# Start the New York (ny) cluster
+run --file=./scripts/start-ny.gfsh
+list members
+disconnect
+
+# Create the region on each cluster and bind the gateway senders/receivers to region
+run --file=./scripts/start-wan.gfsh
+
diff --git a/wan/scripts/stop.gfsh b/wan/scripts/stop.gfsh
new file mode 100644
index 0000000..a482d63
--- /dev/null
+++ b/wan/scripts/stop.gfsh
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#shutdown london site
+connect --locator=localhost[10332]
+shutdown --include-locators=true
+disconnect
+
+#shutdown ny site
+connect --locator=localhost[10331]
+shutdown --include-locators=true
+
diff --git a/wan/src/main/java/org/apache/geode_examples/wan/Example.java b/wan/src/main/java/org/apache/geode_examples/wan/Example.java
new file mode 100644
index 0000000..9b87ccd
--- /dev/null
+++ b/wan/src/main/java/org/apache/geode_examples/wan/Example.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.wan;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.IntStream;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+
+public class Example {
+ private final Region<Integer, String> region;
+
+ public Example(Region<Integer, String> region) {
+ this.region = region;
+ }
+
+ public static void main(String[] args) {
+ // connect to the locator in London cluster using port 10332
+ ClientCache cache = new ClientCacheFactory().addPoolLocator("127.0.0.1", 10332)
+ .set("log-level", "WARN").create();
+
+ // create a local region that matches the server region
+ Region<Integer, String> region =
+ cache.<Integer, String>createClientRegionFactory(ClientRegionShortcut.PROXY)
+ .create("example-region");
+
+ Example example = new Example(region);
+ example.insertValues(10);
+ example.printValues(example.getValues());
+
+ cache.close();
+ }
+
+ Set<Integer> getValues() {
+ return new HashSet<>(region.keySetOnServer());
+ }
+
+ void insertValues(int upperLimit) {
+ IntStream.rangeClosed(1, upperLimit).forEach(i -> region.put(i, "value" + i));
+ }
+
+ void printValues(Set<Integer> values) {
+ values.forEach(key -> System.out.println(String.format("%d:%s", key, region.get(key))));
+ }
+}