1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
Скрыть объявление

Привет посетитель! У нас на форуме тебе откроются дополнительные разделы, которые скрыты от гостей! А так же ты найдёшь много полезной информации.

Скрипт Memory Watching

Уведомлялка о расходе памяти сервера

  1. n3k0Nation
    Простая уведомлялка о критическом состоянии памяти на сервере. Поддерживает дамп памяти (который выпилят в Java 9), если Full GC не произошло (т.к. получается, то все объекты живы и у нас утечка памяти).
    Поддерживает: G1, Marksweep, Scavenge.

    Код:
    package fork2.gs.ext.sys;
    
    import java.lang.management.MemoryPoolMXBean;
    
    /**
     * @author PointerRage
     *
     */
    public interface IMemoryWatcher {
       void register(MemoryPoolMXBean pool);
       boolean isValid(MemoryPoolMXBean pool);
    }
    
    Код:
    package fork2.gs.ext.sys;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.MemoryPoolMXBean;
    import java.lang.management.MemoryType;
    
    import javax.management.NotificationEmitter;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @author PointerRage
     *
     */
    @Slf4j
    public class DefaultWatcher implements IMemoryWatcher {
       protected DefaultWatcher() {
       }
       
       @Override
       public void register(MemoryPoolMXBean pool) {
         long max = pool.getUsage().getMax();
         pool.setUsageThreshold(Math.round(max * 0.85));
         
         NotificationEmitter emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
         emitter.addNotificationListener(new PoolListener(pool), null, null);
         log.info("Listened {}", pool.getName());
       }
    
       @Override
       public boolean isValid(MemoryPoolMXBean pool) { //for marksweep & scavenge
         return pool.getType() == MemoryType.HEAP && pool.isCollectionUsageThresholdSupported() && pool.getName().startsWith("PS Survivor");
       }
    }
    
    Код:
    package fork2.gs.ext.sys;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.MemoryPoolMXBean;
    import java.lang.management.MemoryType;
    
    import javax.management.NotificationEmitter;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @author PointerRage
     *
     */
    @Slf4j
    public class G1Watcher implements IMemoryWatcher {
       protected G1Watcher() {
         
       }
       
       @Override
       public void register(MemoryPoolMXBean pool) {
         long max = pool.getUsage().getMax();
         pool.setUsageThreshold(Math.round(max * 0.85));
         
         NotificationEmitter emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
         emitter.addNotificationListener(new PoolListener(pool), null, null);
         log.info("Listened {}", pool.getName());
       }
       
       @Override
       public boolean isValid(MemoryPoolMXBean pool) { //for G1 GC its old gen
         return pool.getType() == MemoryType.HEAP && pool.isUsageThresholdSupported() && pool.isCollectionUsageThresholdSupported()
             && pool.getName().startsWith("G1");
       }
    }
    
    Код:
    package fork2.gs.ext.sys;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.MemoryNotificationInfo;
    import java.lang.management.MemoryPoolMXBean;
    import java.lang.management.MemoryUsage;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    import javax.management.MBeanServer;
    import javax.management.Notification;
    import javax.management.NotificationListener;
    
    import net.sf.ehcache.config.MemoryUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import ru.catssoftware.gameserver.ThreadPoolManager;
    import ru.catssoftware.gameserver.gmaccess.GmInteract;
    
    import com.sun.management.HotSpotDiagnosticMXBean;
    
    /**
     * @author PointerRage
     *
     */
    public class PoolListener implements NotificationListener {
       private final static Logger memLog = LoggerFactory.getLogger("MemLog");
       private final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd_HH.mm");
       private final MemoryPoolMXBean pool;
       private Future<?> watch;
       
       protected PoolListener(MemoryPoolMXBean pool) {
         this.pool = pool;
       }
       
       @Override
       public void handleNotification(Notification notification, Object handback) {
         if(!notification.getType().equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)
             && !notification.getType().equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED))
           return;
         
         MemoryUsage usage = pool.getUsage();
         long used = usage.getUsed();
         long max = usage.getMax();
         long percent = Math.round((used / (double)max) * 100);
         
         memLog.warn("Critical memory usage {}% for {} pool. Usage: {}/{} mb.",
             percent, pool.getName(), MemoryUnit.BYTES.toMegaBytes(used), MemoryUnit.BYTES.toMegaBytes(max));
         
         GmInteract.getInstance().normalMsg("Critical memory usage {}% for {} pool. Usage: {}/{} mb.",
             percent, pool.getName(), MemoryUnit.BYTES.toMegaBytes(used), MemoryUnit.BYTES.toMegaBytes(max));
         
         if(watch != null && !watch.isDone()) {
           watch.cancel(false);
         }
         watch = ThreadPoolManager.getInstance().scheduleGeneral(() -> watchHeap(percent), 2, TimeUnit.MINUTES);
       }
       
       private void watchHeap(long percent) {
         MemoryUsage usage = pool.getUsage();
         long used = usage.getUsed();
         long max = usage.getMax();
         long actualPercent = Math.round((used / (double)max) * 100);
         
         if(actualPercent > percent) { //is memory leak or full gc?
           dump();
         }
         
         GmInteract.getInstance().normalMsg("Critical memory usage {}% for {} pool. Usage: {}/{} mb.",
             actualPercent, pool.getName(), MemoryUnit.BYTES.toMegaBytes(used), MemoryUnit.BYTES.toMegaBytes(max));
         GmInteract.getInstance().normalMsg("Please reboot server!");
       }
       
       private void dump() {
         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
         HotSpotDiagnosticMXBean diagnosticBean;
         try {
           diagnosticBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
         } catch(Throwable e) {
           memLog.warn("Failed to dump memory.");
           return;
         }
         
         String format = dateFormat.format(new Date());
         try {
           diagnosticBean.dumpHeap("./" + format + ".bin", true);
         } catch (Throwable e) {
           memLog.warn("Failed to dump memory.");
           return;
         }
         
         GmInteract.getInstance().normalMsg("Memory succefull dumped: {}.bin", format);
         memLog.warn("Memory succefull dumped: {}.bin", format);
       }
    
    }
    
    Код:
    package fork2.gs.ext.sys;
    
    import java.lang.management.ManagementFactory;
    import java.lang.management.MemoryPoolMXBean;
    import java.util.Arrays;
    import java.util.List;
    
    import lombok.Getter;
    import lombok.extern.slf4j.Slf4j;
    import fork2.startup.Singleton;
    import fork2.startup.Startup;
    
    /**
     * @author PointerRage
     *
     */
    @Startup("SystemInfo")
    @Singleton
    @Slf4j
    public class MemoryWatchManager {
       @Getter(lazy=true) private final static MemoryWatchManager instance = new MemoryWatchManager();
       private final List<IMemoryWatcher> watchers = Arrays.asList(new G1Watcher(), new DefaultWatcher());
       private MemoryWatchManager() {
         registerWatchers();
       }
       
       private void registerWatchers() {
         for(MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
           log.info("{}: {}", pool.getName(), pool.getUsage().toString());
           watchers.stream()
             .filter(watcher -> watcher.isValid(pool))
             .forEach(watcher -> watcher.register(pool));
         }
       }
    }
    
    Ethernal и kick нравится это.