Я использую Ignite в кластере Kubernetes с включенным постоянством.Каждая машина имеет кучу Java объемом 24 ГБ, из которых 20 ГБ предназначены для надежной памяти с ограничением в 110 ГБ.Мои соответствующие параметры JVM: -XX:+AlwaysPreTouch -XX:+UseG1GC -XX:+ScavengeBeforeFullGC
.После запуска DataStreamers на каждом узле в течение нескольких часов узлы в моем кластере достигли своего предела памяти k8s, вызвав уничтожение OOM.После запуска Java NMT я с удивлением обнаружил огромный объем пространства, выделенного внутренней памяти.
Java Heap (reserved=25165824KB, committed=25165824KB)
(mmap: reserved=25165824KB, committed=25165824KB)
Internal (reserved=42425986KB, committed=42425986KB)
(malloc=42425954KB #614365)
(mmap: reserved=32KB, committed=32KB)
Метрики Kubernetes подтвердили это:
«Ignite Cache» - это кэш страницы ядра.Последняя панель «Heap + Durable + Buffer» представляет собой сумму показателей воспламенения HeapMemoryUsed
+ PhysicalMemorySize
+ CheckpointBufferSize
.
Я знал, что это не может быть результатом накопления данных, потому чтоDataStreamers сбрасываются после каждого прочитанного файла (максимум до 250 МБ), и ни один узел не читает одновременно более 4 файлов.После исключения других проблем с моей стороны я попытался установить -XX:MaxDirectMemorySize=10G
и вызвать ручной сборщик мусора, но, похоже, ничто не повлияло на это, кроме периодического выключения всех моих модулей и их перезапуска.
Яне уверен, куда идти отсюда.Есть ли обходной путь в Ignite, который не заставляет меня использовать стороннюю базу данных?
РЕДАКТИРОВАТЬ: My DataStorageConfiguration
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
<property name="metricsEnabled" value="true"/>
<property name="checkpointFrequency" value="300000"/>
<property name="storagePath" value="/var/lib/ignite/data/db"/>
<property name="walFlushFrequency" value="10000"/>
<property name="walMode" value="LOG_ONLY"/>
<property name="walPath" value="/var/lib/ignite/data/wal"/>
<property name="walArchivePath" value="/var/lib/ignite/data/wal/archive"/>
<property name="walSegmentSize" value="2147483647"/>
<property name="maxWalArchiveSize" value="4294967294"/>
<property name="walCompactionEnabled" value="false"/>
<property name="writeThrottlingEnabled" value="False"/>
<property name="pageSize" value="4096"/>
<property name="defaultDataRegionConfiguration">
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="persistenceEnabled" value="true"/>
<property name="checkpointPageBufferSize" value="2147483648"/>
<property name="name" value="Default_Region"/>
<property name="maxSize" value="21474836480"/>
<property name="metricsEnabled" value="true"/>
</bean>
</property>
</bean>
</property>
ОБНОВЛЕНИЕ: Когда я отключаю постоянство, внутренняя память работает правильноутилизировано:
ОБНОВЛЕНИЕ: проблема продемонстрирована здесь на воспроизводимом примере.Он работает на машине с минимум 22 ГБ памяти для докера и около 50 ГБ памяти.Интересно, что утечка действительно заметна только при передаче в качестве значения байтового массива или строки.