You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by bs...@apache.org on 2020/04/16 15:12:51 UTC
[geode] branch develop updated: GEODE-7852: test
ClientHealthMonitor functionality behind a SNI gateway (#4958)
This is an automated email from the ASF dual-hosted git repository.
bschuchardt pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 9db544e GEODE-7852: test ClientHealthMonitor functionality behind a SNI gateway (#4958)
9db544e is described below
commit 9db544e876088794de58a0f863e13d17134f1e26
Author: Bruce Schuchardt <bs...@pivotal.io>
AuthorDate: Thu Apr 16 08:12:11 2020 -0700
GEODE-7852: test ClientHealthMonitor functionality behind a SNI gateway (#4958)
* GEODE-7852: test ClientHealthMonitor functionality behind a SNI gateway
This ensures that a server sitting behind an SNI gateway detects the
loss of a client and cleans up after it. In this case the test detects
that the server has closed CQs created by the non-durable client.
Since test code is not accessible in the Docker container that's running
the server I've enhanced the StatArchiveReader to be able to report the
values of a statistic and have enabled statistics recording in the
server.
(cherry picked from commit 376df4cc7abc6db38b4b298f8af6f3c53baedf15)
* change the docker rule to be a class-rule in case we add more tests to this class
* removed system.out.println per Bill's review
---
.../client/sni/ClientSNICQAcceptanceTest.java | 72 +++++++++----
.../client/sni/geode-config/gemfire.properties | 3 +-
.../internal/statistics/StatArchiveReader.java | 114 +++++++++++++++++++--
3 files changed, 163 insertions(+), 26 deletions(-)
diff --git a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
index d422807..e5c32c8 100644
--- a/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
+++ b/geode-assembly/src/acceptanceTest/java/org/apache/geode/client/sni/ClientSNICQAcceptanceTest.java
@@ -22,6 +22,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_
import static org.apache.geode.distributed.ConfigurationProperties.SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD;
+import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.apache.geode.test.util.ResourceUtils.createTempFileFromResource;
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,9 +32,11 @@ import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import com.palantir.docker.compose.DockerComposeRule;
+import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.ClassRule;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@@ -42,6 +45,7 @@ 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;
+import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.cache.client.proxy.ProxySocketFactories;
import org.apache.geode.cache.query.CqAttributes;
import org.apache.geode.cache.query.CqAttributesFactory;
@@ -64,14 +68,17 @@ public class ClientSNICQAcceptanceTest {
@ClassRule
public static TestRule ignoreOnWindowsRule = new IgnoreOnWindowsRule();
- @Rule
- public DockerComposeRule docker = DockerComposeRule.builder()
- .file(DOCKER_COMPOSE_PATH.getPath())
- .build();
+ @ClassRule
+ public static NotOnWindowsDockerRule docker =
+ new NotOnWindowsDockerRule(() -> DockerComposeRule.builder()
+ .file(DOCKER_COMPOSE_PATH.getPath()).build());
+
private CqQuery cqTracker;
AtomicInteger eventCreateCounter = new AtomicInteger(0);
AtomicInteger eventUpdateCounter = new AtomicInteger(0);
+ private ClientCache cache;
+ private Region<String, Integer> region;
class SNICQListener implements CqListener {
@@ -94,22 +101,29 @@ public class ClientSNICQAcceptanceTest {
}
}
- private String trustStorePath;
+ private static String trustStorePath;
- @Before
- public void before() throws IOException, InterruptedException {
+ @BeforeClass
+ public static void beforeClass() throws IOException, InterruptedException {
trustStorePath =
createTempFileFromResource(ClientSNICQAcceptanceTest.class,
"geode-config/truststore.jks")
.getAbsolutePath();
- docker.exec(options("-T"), "geode",
+ docker.get().exec(options("-T"), "geode",
arguments("gfsh", "run", "--file=/geode/scripts/geode-starter.gfsh"));
}
- @Test
- public void performSimpleCQOverSNIProxy()
- throws CqException, CqExistsException, RegionNotFoundException {
+ @AfterClass
+ public static void afterClass() throws Exception {
+ String output =
+ docker.get().exec(options("-T"), "geode",
+ arguments("cat", "server-dolores/server-dolores.log"));
+ System.out.println("Server log file--------------------------------\n" + output);
+ }
+
+ @Before
+ public void before() throws Exception {
Properties gemFireProps = new Properties();
gemFireProps.setProperty(SSL_ENABLED_COMPONENTS, "all");
gemFireProps.setProperty(SSL_KEYSTORE_TYPE, "jks");
@@ -119,22 +133,30 @@ public class ClientSNICQAcceptanceTest {
gemFireProps.setProperty(SSL_TRUSTSTORE_PASSWORD, "geode");
gemFireProps.setProperty(SSL_ENDPOINT_IDENTIFICATION_ENABLED, "true");
- int proxyPort = docker.containers()
+ int proxyPort = docker.get().containers()
.container("haproxy")
.port(15443)
.getExternalPort();
- ClientCache cache = new ClientCacheFactory(gemFireProps)
+ cache = new ClientCacheFactory(gemFireProps)
.addPoolLocator("locator-maeve", 10334)
.setPoolSocketFactory(ProxySocketFactories.sni("localhost",
proxyPort))
.setPoolSubscriptionEnabled(true)
.create();
- Region<String, Integer> region =
- cache.<String, Integer>createClientRegionFactory(ClientRegionShortcut.PROXY)
- .create("jellyfish");
+ region = cache.<String, Integer>createClientRegionFactory(ClientRegionShortcut.PROXY)
+ .create("jellyfish");
+ }
- startCQ(region);
+ @After
+ public void after() throws Exception {
+ if (cache != null) {
+ cache.close();
+ }
+ }
+ @Test
+ public void performSimpleCQOverSNIProxy() throws Exception {
+ startCQ(region);
populateRegion(region);
assertThat(region.get("key0")).isEqualTo(0);
assertThat(region.get("key1")).isEqualTo(1);
@@ -152,6 +174,20 @@ public class ClientSNICQAcceptanceTest {
assertThat(eventUpdateCounter.get()).isEqualTo(62);
+ // verify that the server cleans up when the client connection to the gateway is destroyed
+ ((PoolImpl) cache.getDefaultPool()).killPrimaryEndpoint();
+ // since we can't run code in the server let's grab the CQ statistics and verify that
+ // the CQ has been closed. StatArchiveReader has a main() that we can use to get a printout
+ // of stat values
+ await().untilAsserted(() -> {
+ String stats = docker.get().exec(options("-T"), "geode",
+ arguments("java", "-cp", "/geode/lib/geode-dependencies.jar",
+ "org.apache.geode.internal.statistics.StatArchiveReader",
+ "stat", "server-dolores/statArchive.gfs", "CqServiceStats.numCqsClosed"));
+ // the stat should transition from zero to one at some point
+ assertThat(stats).contains("0.0 1.0");
+ });
+
}
public void updateRegion(Region<String, Integer> region) {
diff --git a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/gemfire.properties b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/gemfire.properties
index 213cabe..1f13fb0 100644
--- a/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/gemfire.properties
+++ b/geode-assembly/src/acceptanceTest/resources/org/apache/geode/client/sni/geode-config/gemfire.properties
@@ -15,4 +15,5 @@
# limitations under the License.
#
-#empty
+statistic-sampling-enabled=true
+statistic-archive-file=statArchive.gfs
diff --git a/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveReader.java b/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveReader.java
index 25670c3..a62e311 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveReader.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveReader.java
@@ -210,21 +210,121 @@ public class StatArchiveReader implements StatArchiveFormat, AutoCloseable {
}
}
+ private static class SingleStatRawStatSpec implements StatSpec {
+
+ private final String archive;
+ private final String statType;
+ private final String statName;
+
+ SingleStatRawStatSpec(String archive, String typeAndStat) {
+ this.archive = archive;
+ String[] parts = typeAndStat.split("\\.", 0);
+ this.statType = parts[0];
+ this.statName = parts[1];
+ }
+
+ @Override
+ public boolean archiveMatches(File archive) {
+ return true; // this.archive.equalsIgnoreCase(archive.getName());
+ }
+
+ @Override
+ public boolean typeMatches(String typeName) {
+ return this.statType.equalsIgnoreCase(typeName);
+ }
+
+ @Override
+ public boolean statMatches(String statName) {
+ return this.statName.equalsIgnoreCase(statName);
+ }
+
+ @Override
+ public boolean instanceMatches(String textId, long numericId) {
+ return true;
+ }
+
+ @Override
+ public int getCombineType() {
+ return StatSpec.NONE;
+ }
+ }
+
+ private static void printStatValue(StatArchiveReader.StatValue v, long startTime, long endTime,
+ boolean nofilter, boolean persec, boolean persample, boolean prunezeros, boolean details) {
+ v = v.createTrimmed(startTime, endTime);
+ if (nofilter) {
+ v.setFilter(StatArchiveReader.StatValue.FILTER_NONE);
+ } else if (persec) {
+ v.setFilter(StatArchiveReader.StatValue.FILTER_PERSEC);
+ } else if (persample) {
+ v.setFilter(StatArchiveReader.StatValue.FILTER_PERSAMPLE);
+ }
+ if (prunezeros) {
+ if (v.getSnapshotsMinimum() == 0.0 && v.getSnapshotsMaximum() == 0.0) {
+ return;
+ }
+ }
+ System.out.println(" " + v.toString());
+ if (details) {
+ System.out.print(" values=");
+ double[] snapshots = v.getSnapshots();
+ for (int i = 0; i < snapshots.length; i++) {
+ System.out.print(' ');
+ System.out.print(snapshots[i]);
+ }
+ System.out.println();
+ String desc = v.getDescriptor().getDescription();
+ if (desc != null && desc.length() > 0) {
+ System.out.println(" " + desc);
+ }
+ }
+ }
+
+
/**
* Simple utility to read and dump statistic archive.
*/
public static void main(String args[]) throws IOException {
String archiveName = null;
+ final StatArchiveReader reader;
if (args.length > 1) {
- System.err.println("Usage: [archiveName]");
- ExitCode.FATAL.doSystemExit();
- } else if (args.length == 1) {
- archiveName = args[0];
+ if (!args[0].equals("stat") || args.length > 3) {
+ System.err.println("Usage: stat archiveName statType.statName");
+ ExitCode.FATAL.doSystemExit();
+ }
+ archiveName = args[1];
+ String statSpec = args[2];
+ if (!statSpec.contains(".")) {
+ throw new IllegalArgumentException(
+ "stat spec '" + statSpec + "' is malformed - use StatType.statName");
+ }
+ File archiveFile = new File(archiveName);
+ if (!archiveFile.exists()) {
+ throw new IllegalArgumentException("archive file does not exist: " + archiveName);
+ }
+ if (!archiveFile.canRead()) {
+ throw new IllegalArgumentException("archive file exists but is unreadable: " + archiveName);
+ }
+ File[] archives = new File[] {archiveFile};
+ SingleStatRawStatSpec[] filters =
+ new SingleStatRawStatSpec[] {new SingleStatRawStatSpec(archiveName, args[2])};
+ reader = new StatArchiveReader(archives, filters, false);
+ final StatValue[] statValues = reader.matchSpec(filters[0]);
+ System.out.println(statSpec + " matched " + statValues.length + " stats...");
+ for (StatValue value : statValues) {
+ printStatValue(value, -1, -1, true, false, false, false, true);
+ }
+ System.out.println("");
+ System.out.flush();
} else {
- archiveName = "statArchive.gfs";
+ if (args.length == 1) {
+ archiveName = args[0];
+ } else {
+ archiveName = "statArchive.gfs";
+ }
+ reader = new StatArchiveReader(archiveName);
+ System.out.println("DEBUG: memory used = " + reader.getMemoryUsed());
}
- StatArchiveReader reader = new StatArchiveReader(archiveName);
- System.out.println("DEBUG: memory used = " + reader.getMemoryUsed());
reader.close();
}