如何配置非持久性 Ignite 以防止交换?

How to configure non-persistent Ignite to prevent swapping?

我的 JBoss 7.1.6 EAP 部署 -Xmx8g VM 上的物理 RAM 设置为 12 GB。我在初始化 Apache Ignite 缓存时出现一条日志消息:

stdout:71 - [08:54:52] Nodes started on local machine require more than 80% of physical RAM what can lead to significant slowdown due to swapping (please decrease JVM heap size, data region size or checkpoint buffer size) [required=10662MB, available=11834MB]

我完全以编程方式使用 Ignite,我没有使用持久性。这是我的代码:

System.setProperty("IGNITE_UPDATE_NOTIFIER", "false");

igniteConfiguration = new IgniteConfiguration();

int failureDetectionTimeout = Integer.parseInt(getProperty("IGNITE_TCP_DISCOVERY_FAILURE_DETECTION_TIMEOUT", "60000"));

igniteConfiguration.setFailureDetectionTimeout(failureDetectionTimeout);

String igniteVmIps = getProperty("IGNITE_VM_IPS");
List<String> addresses = Arrays.asList("127.0.0.1:47500");
if (StringUtils.isNotBlank(igniteVmIps)) {
    addresses = Arrays.asList(igniteVmIps.split(","));
}

int networkTimeout = Integer.parseInt(getProperty("IGNITE_TCP_DISCOVERY_NETWORK_TIMEOUT", "60000"));
boolean failureDetectionTimeoutEnabled = Boolean.parseBoolean(getProperty("IGNITE_TCP_DISCOVERY_FAILURE_DETECTION_TIMEOUT_ENABLED", "true"));

int tcpDiscoveryLocalPort = Integer.parseInt(getProperty("IGNITE_TCP_DISCOVERY_LOCAL_PORT", "47500"));
int tcpDiscoveryLocalPortRange = Integer.parseInt(getProperty("IGNITE_TCP_DISCOVERY_LOCAL_PORT_RANGE", "0"));

TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
tcpDiscoverySpi.setLocalPort(tcpDiscoveryLocalPort);
tcpDiscoverySpi.setLocalPortRange(tcpDiscoveryLocalPortRange);
tcpDiscoverySpi.setNetworkTimeout(networkTimeout);
tcpDiscoverySpi.failureDetectionTimeoutEnabled(failureDetectionTimeoutEnabled);
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(addresses);
tcpDiscoverySpi.setIpFinder(ipFinder);

igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);

Ignite ignite = Ignition.start(igniteConfiguration);

ignite.cluster().active(true);

// later, initialize my caches
String cacheName = cacheEnum.name();
CacheConfiguration<String, byte[]> cacheCfg = new CacheConfiguration<>(cacheName);
int maxSize = Integer.parseInt(StringUtils.defaultIfBlank(
        PropertyHelper.lookupProperty(String.format(CACHE_SETTING_FORMAT, cacheName, ObjectCacheConstants.SETTING_MAX_SIZE)),
        String.valueOf(ObjectCacheConstants.SETTING_MAX_SIZE_DEFAULT)));
long expiresAfterMs = Long.parseLong(StringUtils.defaultIfBlank(
        PropertyHelper.lookupProperty(String.format(CACHE_SETTING_FORMAT, cacheName, ObjectCacheConstants.SETTING_EXPIRES_MS)),
        String.valueOf(ObjectCacheConstants.SETTING_EXPIRES_MS_DEFAULT)));

cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cacheCfg.setBackups(1);

cacheCfg.setOnheapCacheEnabled(true);
cacheCfg.setEvictionPolicyFactory(new LruEvictionPolicyFactory<String, byte[]>(maxSize));

Optional<CreatedExpiryPolicy> expiryPolicy = Optional.empty();
if (expiresAfterMs > 0) {
    expiryPolicy = Optional.of(new CreatedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, expiresAfterMs)));
}

我在谷歌上搜索了这个警告,但我找到的所有解决方案都涉及更新持久性设置,但我没有使用持久性。

在我的例子中,没有缓存我们可以在 2GB 堆上运行没问题。所以我留下 6GB 用于缓存,这应该绰绰有余。我想对其进行设置,以便我的 JVM 使用最多 6G 的内存,而不是更多。

为了让我的程序获得正确的 ram 使用率,我应该考虑更改哪些字段?

Ignite 中有一个启发式算法,即 4GB 或 20% 的可用内存不应被节点占用,以防止 OS 开始交换 Ignite 节点操作的内存。当然,这完全取决于您的 OS 设置。节点所需的全部内存量计算为堆内存和堆外内存的总和。堆内存基本上是您的 JVM Xmx 设置减去一些 GC 开销。堆外是所有 data region sizes along with their checkpoint buffer sizes (if one has a persistence enabled for a region). I suppose in your case it's just a default 区域的总和,没有持久化,所以它是 0 用于检查点缓冲区。默认情况下,它是可用内存的 20% 或默认区域本身至少 256Mb。您在这里有一些选择:

  • 如果您完全确定 OS 交换设置并且同一台机器上没有任何消费软件 运行,请忽略。
  • 增加OS内存。
  • 调整 Xmx 使其变小。
  • 减少默认区域(实际上不推荐,但仍然是一个选项)而不为该区域打开持久性。
  • 结合上面的一些。