HazelcastMonitoringService.java
package com.tradecloud.config;
import com.hazelcast.config.Config;
import com.hazelcast.config.MapConfig;
import com.hazelcast.core.DistributedObject;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.map.IMap;
import com.hazelcast.map.LocalMapStats;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
@DependsOn("hazelcastInstance")
public class HazelcastMonitoringService {
private static final Logger log = Logger.getLogger(HazelcastMonitoringService.class);
@Autowired
private HazelcastInstance hazelcastInstance;
@PostConstruct
public void clearAllMapsOnStartup() {
log.info("Starting Hazelcast startup cleanup...");
String lockKey = "hz-startup-clear-lock";
IMap<String, Boolean> lockMap = hazelcastInstance.getMap("startup-lock-map");
// try to acquire "lock"
Boolean acquired = lockMap.putIfAbsent(lockKey, true);
if (acquired == null) { // we got the lock
try {
hazelcastInstance.getDistributedObjects().forEach(obj -> {
if (obj instanceof IMap<?, ?> map) {
log.info("Clearing Hazelcast map: " + map.getName());
map.clear();
}
});
log.info("Hazelcast startup cleanup completed.");
} finally {
lockMap.delete(lockKey); // release lock
}
} else {
log.info("Another node is already doing startup cleanup. Skipping.");
}
}
@PreDestroy
public void onShutdown() {
// This stops the heartbeat threads immediately
// before the WebappClassLoader is destroyed
if (hazelcastInstance != null) {
log.info("Hazelcast proper shutdown..");
hazelcastInstance.getLifecycleService().shutdown();
}
}
// Runs every 5 minutes (300,000 milliseconds)
//@Scheduled(fixedRate = 120_000)
public void runMemoryAudit() {
Config config = hazelcastInstance.getConfig();
long totalClusterHeap = 0;
log.info("========== HAZELCAST PERIODIC AUDIT ==========");
for (DistributedObject obj : hazelcastInstance.getDistributedObjects()) {
if (obj instanceof IMap map) {
MapConfig mCfg = config.findMapConfig(map.getName());
LocalMapStats stats = map.getLocalMapStats();
long heapCost = stats.getHeapCost();
totalClusterHeap += heapCost;
// Log Config vs Actuals
log.info(String.format(
"MAP: %-30s | Max: %d | Current: %d | Format: %s | Memory: %.2f MB",
map.getName(),
mCfg.getEvictionConfig().getSize(),
stats.getOwnedEntryCount(),
mCfg.getInMemoryFormat(),
heapCost / (1024.0 * 1024.0)
));
}
// JVM Context
long maxMemory = Runtime.getRuntime().maxMemory();
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
long usedMemory = totalMemory - freeMemory;
log.info(String.format("TOTAL HZ USAGE: %.2f MB", totalClusterHeap / (1024.0 * 1024.0)));
log.info(String.format("JVM HEAP: Used: %.2f MB / Max: %.2f MB (%.1f%%)",
usedMemory / (1024.0 * 1024.0),
maxMemory / (1024.0 * 1024.0),
(usedMemory * 100.0 / maxMemory)));
log.info("===============================================");
}
}
}