是否可以在一个 JVM 中启动 PIvotal GemFire 服务器、定位器和客户端?

Is it possible to start a PIvotal GemFire Server, Locator and Client in one JVM?

我想使用 Spring Boot.

在单个 JVM 中启动 Pivotal GemFire 服务器、定位器和客户端

服务器和定位器启动正常(我在服务器gemfire.properties中使用了"start-locator")。

但是,当我尝试启动连接到定位器的客户端时,出现异常:

java.lang.IllegalStateException: A connection to a distributed system already exists in this VM. 

    at com.gemstone.gemfire.distributed.internal.InternalDistributedSystem.validateSameProperties(InternalDistributedSystem.java:3054)
    at com.gemstone.gemfire.distributed.DistributedSystem.connect(DistributedSystem.java:1642)

并且,在异常中,打印出服务器用于连接到定位器的现有属性。

这是客户端的代码:

@Bean(name = "GemfireClientProperties")
Properties gemfireClientProperties() {
    Properties gemfireProperties = new Properties();
    gemfireProperties.setProperty("mcast-port", "0");
    gemfireProperties.setProperty("log-level", "config");
    return gemfireProperties;
}


@Bean(name = "GemfireClientPool")
PoolFactoryBean gemfireClientPool() {
    PoolFactoryBean gemfirePool = new PoolFactoryBean();
    gemfirePool.setRetryAttempts(1);
    gemfirePool.setLocators(Collections.singletonList(new ConnectionEndpoint("localhost", 17202)));
    return gemfirePool;
}


@Bean(name = "clientCache")
ClientCache clientCache(@Qualifier("GemfireClientProperties") Properties gemfireClientProperties) {
    ClientCacheFactory clientCacheFactory = new ClientCacheFactory(gemfireClientProperties);
    return clientCacheFactory.create();
}

Pivotal GemFire 版本为 8.2.5。

我在调试模式下跟踪,在clientCacheFactory.create()行抛出异常,在方法中,传入的属性文件是正确的,只有2个条目。

Pivotal GemFire 是否有一些限制,以至于我无法通过这种方式连接?

是的,这是已知的限制,每个 JVM 的缓存不能超过一个(具有嵌入式定位器的服务器除外)。 干杯。

简而言之,不,您不能在同一个 JVM(或 Java 应用程序进程)中拥有对等 Cache 实例(带有嵌入式定位器)和 ClientCache 实例。

在 Apache Geode/Pivotal GemFire 中,缓存实例,无论是对等 Cache(分布式系统或集群的对等成员)还是 ClientCache 实例,都是一个单例。 因此,每个 JVM 只能有 1 个 GemFire 缓存实例(或者更专业地说,ClassLoader,但我们不会走那条丑陋的路)。

无论如何,当缓存实例已经存在时,任何后续的缓存创建尝试都会说,使用 GemFire 的 o.a.g.cache.client.ClientCacheFactory (when a peer Cache instance, created by the o.a.g.cache.CacheFactory 创建的 ClientCache 实例已经存在)将导致检查 GemFire 几乎在哪里期望缓存实例相同(即存在对等 Cache,因此最好尝试创建相同的(通过配置,无论如何)"peer" Cache 实例)。显然,ClientCache 实例将不会具有与对等 Cache 实例相同的(分布式系统)配置,因此失败。

你可以看到开始的逻辑here. The first thing that a cache instance creation does is check and lookup an existing cache instance. A ClientCache instance cannot have the locators and mcast-port properties set (here);如果是,则会导致错误(通常是客户端和对等缓存实例之间的另一个差异,特别是 locators 属性)。

如果现有实例没有关闭或正在关闭,那么它将validate the configuration。创建另一个缓存实例的唯一方法几乎是当它是同一个实例时。配置验证非常广泛。

在 Apache Geode 开发列表中讨论过更改 GemFire 缓存实例的“Singletone”性质,但没有讨论在这方面已经实现,但因为它是一项重大任务,部分原因是 static (Client)CacheFactory.getAnyInstance()(或更糟,GemFireCacheImpl.getInstance();对等和客户端缓存实例共享相同的基础 class... org.apache.geode.cache.internal.GemFireCacheImpl) 在整个代码库中被广泛使用,而不是将缓存实例传递给依赖的 GemFire objects/components,例如像 地区.

无论如何,很抱歉这个回答不能给您任何安慰。

但是,我经常创建 2 个单独的 Spring Boot 应用程序(classes)来配置和 bootstrap 两者都是 client and 1 or more servers, 个人.

在服务器上,我什至使用 Spring profile to active a Locator/Manager in a single server instance so that I can form a small cluster (with the embedded Locator) and Manager 这样我也可以使用 Gfsh.

连接到这个集群

因此,您可以使用相同的 class 来启动一个小型集群。第一个服务器将声明为:

$java -cp ... -Dspring.profiles.active=locator-manager example.app.geode.cache.server. GeodeServerApplication

加入第一台服务器的后续服务器将使用:

$java -cp ... -Dspring.data.gemfire.name=ServerTwo -Dspring.data.gemfire.cache.server.port=42424 example.app.geode.cache.server. GeodeServerApplication

注意,您必须注意成员名称(使用 spring.data.gemfire.name 属性 因为 GemFire 要求对等成员名称是唯一的)并且您必须改变 CacheServer 端口(由缓存客户端用于连接;因此 spring.data.gemfire.cache.server.port 属性)否则您将点击 java.net.BindException,因为默认情况下 CacheServer 侦听端口 40404

众所周知的 SDG(系统)属性是改变配置和获得小型集群的最简单方法 运行(甚至没有 Gfsh;酷!) .