首页 > 解决方案 > 是否可以在一个 JVM 中启动 Pivotal GemFire 服务器、定位器和客户端?

问题描述

我想使用Spring Boot在单个 JVM 中启动 Pivotal GemFire 服务器、定位器和客户端。

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

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

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。

我在debug模式下跟踪,在clientCacheFactory.create()行抛出异常,在方法中,传入的properties文件是正确的,只有2个entry。

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

标签: gemfirespring-data-gemfire

解决方案


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

在 Apache Geode/Pivotal GemFire 中,缓存实例,无论是对等Cache点(分布式系统或集群的对等成员)还是ClientCache实例,都是Singleton。因此,每个 JVM 只能有 1 个 GemFire 缓存实例(或者从技术上讲ClassLoader,,但我们不会走那条丑陋的道路)。

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

你可以看到从这里开始的逻辑。创建缓存实例的第一件事是检查和查找现有的缓存实例。ClientCache实例不能设置locatorsandmcast-port属性(此处;如果是,则会导致错误(通常是客户端和对等缓存实例之间的另一个差异,特别是对于locators属性)。

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

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

无论如何,对不起,这个答案并没有给你任何安慰。

但是,我经常创建 2 个单独的Spring Boot应用程序(类)来分别配置和引导一个客户端和 1 个或多个服务器

在服务器上,我什至使用Spring 配置文件在单个服务器实例中激活 Locator/Manager ,这样我就可以形成一个小型集群(带有嵌入式 Locator)和Manager,这样我也可以使用Gfsh连接到这个集群。

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

$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属性)否则您将点击 a java.net.BindException,因为默认情况下CacheServer监听端口40404

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


推荐阅读