Apache Ignite IGFS 不使用非堆 Space

Apache Ignite IGFS Not using Non Heap Space

我正在使用 Apache Ignite 2.6。我正在使用 Ignite 文件系统,当我一遍又一遍地将大约 25 MB 的特定文件写入 IGFS 时,数据没有保存到非堆中 space。相反,它进入堆,受垃圾收集的影响,而且速度相对较慢。我如何让 IGFS 将文件保存到我为它分配的大堆 space?

高级架构——我现在在 tomcat 中有一个客户端点燃节点 运行,还有一个服务器点燃节点,我打算在其上存储这些数据。一旦我按预期工作,就会发生缩放——但由于上述问题,它非常慢。当它很快用完堆 space 时,它也会 OOM。问题是,我想让它使用30G的NON HEAP space 我已经分配了!

我打算将其作为 内存中 缓存。我正在为 JVM 分配 2 G 的堆 space 和 30G 的非堆 space。非堆 space 永远不会被使用,结果它耗尽了内存。我已经确认未使用 JMX 控制台内存选项卡使用非堆 space——非堆 space 保持远低于 100M,而堆 space 迅速膨胀到 2G 然后JVM 崩溃。

详情:首先是我的ignite配置(spring xml):

 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_FALLBACK"/>
    <property name="searchSystemEnvironment" value="true"/>
</bean>
<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="marshaller">
        <bean class="org.apache.ignite.internal.binary.BinaryMarshaller" />
    </property>

    <property name="fileSystemConfiguration">
        <list>
            <bean class="org.apache.ignite.configuration.FileSystemConfiguration">
                <property name="name" value="igfs"/>
                <property name="blockSize" value="#{128 * 1024}"/>
                <property name="perNodeBatchSize" value="512"/>
                <property name="perNodeParallelBatchCount" value="16"/>
                <property name="prefetchBlocks" value="32"/>
            </bean>
        </list>
    </property>

    <property name="discoverySpi">
        <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
            <property name="ipFinder">
                <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
                    <property name="addresses">
                        <list>
                            <value>127.0.0.1:47500..47509</value>
                        </list>
                    </property>
                </bean>
            </property>
        </bean>
    </property>
    <property name="dataStorageConfiguration">
        <bean class="org.apache.ignite.configuration.DataStorageConfiguration" >
            <!-- if I don't set this, the system region runs out of memory almost immediately -->
            <property name="systemRegionMaxSize" value="#{6L * 1024 * 1024 * 1024"} />
            <property name="systemRegionInitialSize" value="#{6L * 1024 * 1024 * 1024"} />
        </bean>

    </property>
</bean>

这是我用来启动 ignite 服务器进程的脚本。这是 shell 脚本 运行 在 Linux 机器上,有 64 G RAM 和 40 G 磁盘 space。

IGNITE_HOME=/data/apache-ignite
export IGNITE_HOME
IGNITE_JMX_PORT=1234
export IGNITE_JMX_PORT
$IGNITE_HOME/bin/ignite.sh $IGNITE_HOME/ignite-media-server.xml -J-Xmx2G -J-Xms2G -J-XX::+HeapDumpOnOutOfMemoryError -J-XX:HeapDumpPath=$IGNITE_HOME -J-XX:+PrintGC -J-XX:+PrintGCTimeStamps -J-XX:+PrintGCDateStamps -J-Xloggc:$IGNITE_HOME/gc.log-$(date +%m%d-%H%M%S) -J-XX:+UseG1GC -J-XX:DisableExplicitGC -J-XX:MaxDirectMemorySize=30G 

这是创建我的客户端 igfs 对象的代码,我通过它保存要点燃的文件。他们往往偏大。

public void init() throws Exception{
    igniteInstanceName = "client-name=" + hostInfo.getLocalHost();
    Ignition.setClientMode(true); 
    // reading in the same config file as the server uses to start up above.  The big difference is the clientMode set to true here. 
    try(InputStream configFileInputStream = new FileInputStream(ResourceUtils.getFile("ignite-media-server.xml"));){
         ignite = IgnitionEx.start(configFileInputStream, igniteInstanceName, null, null);
         igfs = ignite.fileSystem("igfs");

    }
    catch(Throwable t){ /* do log */}

}

这是一种保存方法,可以将我的文件保存到 ignite:

public saveStream(String cachePath, AudioInputStream toCache){
   OutputStream os = null;
   try{
       IgfsPath cacheFile = new IgfsPath(cachePath);
       os = igfs.create(cacheFile, true);
       AudioSystem.write(toCache.getDataStream, AudioFileFormat.TYPE.WAVE, os);
   }
   finally{
      // close streams
   }
}

为什么我的数据没有保存到快速堆外 space?我错过了什么?我的 server.config 几乎直接来自 igfs 提供的示例。

在其他混乱中,当我使用 ignitevisor.cmd 检查服务器节点上的内存使用情况之前和之后的较短测试(不会使其崩溃)时,我看到以下内容:

在 ignitevisor.cmd 中 ignite 为空时查看内存分配。看到我的 igfs 区域说:

在 IGFS 中创建仅 SHY 2 G 的文件——仅差一个 OOM,因为从痛苦的经历中我知道它很快就会爆炸。使用ignitevisor.cmd查看节点的内存分配情况。这就是... – MeowCode 2 分钟前

为什么非堆中仍然几乎没有?为什么 ignitevisor 认为非堆最大值是 744 MB 而它应该是 30 GB?

在其他兴趣点上,如果我将堆大小增加到 6 GB,它运行时间会更长,但服务器仍然会崩溃并显示 "OutOfMemoryError:Java heap space"。有趣的是,即使启用磁盘持久性,我也可以重现这一点。检查堆转储文件会发现很多 ConcurrentLinkedHashMap 条目。条目本身是 "org.apache.ignite.internal.GridTopic" 个对象。每个都有一个 uuid,大多数似乎是 TOPIC_DATASTREAM 类型。

数据已经保存到堆外了,但是你应该知道,IGFS 操作中涉及的很多临时对象仍然会短暂地保存在堆上(然后被 GC)。

"JMX Console Memory tab--non heap space" 是错误的指标。我认为堆外没有任何 JVM 指标。但是,Ignite 会定期打印 Off-Heap 统计信息。

为什么会 运行 内存不足并不明显。您是否尝试过收集堆转储并对其进行分析?