Ignite heap 不释放,这是内存泄漏?

Ignite heap not release, this is a memery leak?

我进行了 20 分钟的压力测试,在此期间,免费的 JVM 堆大小从 97% 下降到 3%。即使我等了 5 个小时,免费的数量 space 也没有改变。如果我再次尝试进行测试,GC 的工作量太大并导致长时间的 JVM 暂停。我使用 2.7 Ignite,我不在 tje 堆上保存数据,我用 jdbcthin 保存数据。
本来以为等我测试完了,JVM heap 就会实现了,结果好像不是。

我在下面附上了 JVM 属性和配置。

JVM 属性

JVM_OPTS="$JVM_OPTS -Xms10g -Xmx10g -server"
JVM_OPTS="$JVM_OPTS -XX:+AlwaysPreTouch"
JVM_OPTS="$JVM_OPTS -XX:+UseParNewGC"
JVM_OPTS="$JVM_OPTS -XX:+UseConcMarkSweepGC"
JVM_OPTS="$JVM_OPTS -XX:+CMSClassUnloadingEnabled"
JVM_OPTS="$JVM_OPTS -XX:+CMSPermGenSweepingEnabled"
JVM_OPTS="$JVM_OPTS -XX:+ScavengeBeforeFullGC"
JVM_OPTS="$JVM_OPTS -XX:+CMSScavengeBeforeRemark"
JVM_OPTS="$JVM_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/alidata/soft/ignite/heapdump -XX:+ExitOnOutOfMemoryError"
JVM_OPTS="$JVM_OPTS -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintAdaptiveSizePolicy"
JVM_OPTS="$JVM_OPTS -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Xloggc:/alidata/soft/ignite/gc/gc.log"

配置属性

<bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">

    <!-- Configure internal thread pool. -->
    <property name="publicThreadPoolSize" value="96"/>

    <!-- Configure system thread pool. -->
    <property name="systemThreadPoolSize" value="16"/>

    <!-- Configure query thread pool. -->
    <property name="queryThreadPoolSize" value="96"/>

    <property name="systemWorkerBlockedTimeout" value="#{60 * 60 * 1000}"/>

    <property name="failureHandler">
        <bean class="org.apache.ignite.failure.StopNodeFailureHandler"/>
    </property>
        <!-- Enabling Apache Ignite native persistence. -->
  <property name="dataStorageConfiguration">
    <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
      <!-- Enable write throttling.-->
      <property name="writeThrottlingEnabled" value="true"/>
      <!-- Set concurrency level -->
      <property name="concurrencyLevel" value="4"/>

      <property name="defaultDataRegionConfiguration">
        <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
          <property name="persistenceEnabled" value="true"/>
          <!-- Increasing the buffer size to 1 GB. -->
          <property name="checkpointPageBufferSize"
                    value="#{1 * 1024L * 1024 * 1024}"/>
          <!-- Setting the size of the default region to 4GB. -->
           <!-- 1 GB initial size. -->
          <property name="initialSize" value="#{1L * 1024 * 1024 * 1024}"/>
          <property name="maxSize" value="#{8L * 1024 * 1024 * 1024}"/>

          <!-- Enabling RANDOM_2_LRU eviction for this region.  -->
            <property name="pageEvictionMode" value="RANDOM_2_LRU"/>
        </bean>
      </property>
      <!-- Size of the WAL (Write Ahead Log) segment -->
      <property name="walSegmentSize" value="#{1 * 1024 * 1024 * 1024}"/>

      <property name="walCompactionEnabled" value="true" />

      <property name="walCompactionLevel" value="1" />

      <!-- Set the page size to 4 KB -->
      <property name="pageSize" value="#{4 * 1024}"/>
      <!--
          Sets a path to the root directory where data and indexes are
          to be persisted. It's assumed the directory is on a separated SSD.
      -->
      <property name="storagePath" value="/alidata/soft/ignite/persistence"/>

      <!--
          Sets a path to the directory where WAL is stored.
          It's assumed the directory is on a separated HDD.
      -->
      <property name="walPath" value="/alidata/soft/ignite/wal"/>

      <!--
          Sets a path to the directory where WAL archive is stored.
          The directory is on the same HDD as the WAL.
      -->
      <property name="walArchivePath" value="/alidata/soft/ignite/wal/"/>
    </bean>
  </property>
  <property name="discoverySpi">
    <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
      <property name="failureDetectionTimeout" value="60000"/>
      <property name="ipFinder">
        <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
          <property name="addresses">
            <list>
              <value>172.16.14.14:47500..47509</value>
              <value>172.16.14.15:47500..47509</value>
              <value>172.16.14.16:47500..47509</value>
              <value>172.16.14.17:47500..47509</value>
            </list>
          </property>
        </bean>
      </property>
    </bean>
  </property>
   </bean>

3% 图片

你能给我一些解决这个问题的建议吗?

Apache Ignite 不会使用太多的堆,除非你碰巧使用了堆上缓存。

请确保您在测试期间没有在堆上保留太多数据。

我建议收集一个堆转储,用例如Eclipse MAT 看看那里发生了什么。

我可以看到堆由 ConnectionManager.usedConns 持有。

但是,没有已发布的具有 ConnectionManager class 的 Apache Ignite 版本。它肯定不在 2.7.

如果您使用的是 master 分支中的某种您自己的构建,那您就只能靠自己了。考虑从 ignite-2.8 分支升级到最新版本,这个问题可能在那里得到解决。该版本尚未发布,但代码可用并且可能比您正在使用的任何代码都更稳定。

无论哪种方式。您不是真正的 运行 Apache Ignite,当然也不是 AI 2.7。

如果您没有足够的时间提供小型复制器,请描述您的压力情景。调查真的很重要。 ConnectionManager.usedConn 处大量连接的主要原因未关闭 JDBC 本机 API 处的连接和查询游标 (QueryCursor)。

AI 2.7 使用 ThreadLocal 连接并且在简单情况下潜在的泄漏更少。 我们不得不更改连接管理器逻辑以执行 "lazy" 模式(以减少大量结果集的堆使用)。