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" 模式(以减少大量结果集的堆使用)。
我进行了 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" 模式(以减少大量结果集的堆使用)。