如何监控服务的内存指标

79 阅读4分钟

程序员冈刀,目前就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。


1. 为什么要监控服务的指标?

在当今的互联网时代,哪家提供的服务越稳定,这样的的服务越会受到特别的关注。监控服务的各个指标,可以很轻松地了解到当前服务的运行的状态以及是否需要进一步的处理。监控指标是维护一个服务稳定性的必要手段,使用者可以提前地接收到服务的报警以及相关指标的数据变化。最终的目标显而易见,就是维护服务的稳定性。

2. 如何维护服务系统的稳定性?

维护系统的稳定性,实际上有很多的手段,在本文中,按照事件发生的事前、事中、事后这样的事件序列依次介绍每个时间段,可以做的事情。

  • 事前: 此刻服务稳定性没有受到核心的影响。此时,可以监控服务的各项指标,例如:JVM新生代、老年代的使用比率,GC次数等等指标。同时,也可以监控核心接口API的TP X(X为50、90、99等等)的响应时间。当某一项指标无法满足心中预期的时候,及时的报警,然后进行处理。
  • 事中: 此刻服务的稳定性正在遭受严重的威胁,如果不进行及时的处理,有可能导致服务的不可用,进而导致服务的雪崩的发生。此刻我们应该做的是尽可能地将损失降到最低。“先止损,再处理” 在这个阶段非常的实用。But,作为新手,完全不知道处理流程岂不是佷蒙蒙的。所以,线上一分钟、线下十年功,注重平时的养成,用于一时。写好各种SOP以及处理的解决方案,势在必行。最后,也应当进行适当的故障演练。
  • 事后: 也就是事件发生之后,服务已经恢复到了原来的可用程度。此刻似乎也没有什么可以做了!No,No,No!!!此刻应该做的是针对此次事件发生做一次完美的复盘。总结自己的不足,不断的训练自己,下次类似事件发生的时候可以迅速的解决这个问题,减少损失,减少处理时间。
    所以说,维护一个服务的稳定性并不是很简单的把代码写好就好,还需要考虑很多的事情呢。

3. 如何监控JVM指标?

服务稳定性是一个很大的话题,在本文中,主要针对本身应用如何获取、监控JVM指标进行阐述。使用JDK自带的工具获取信息不是本文的重点,本文的重点是使用Java代码获取JVM的使用。在JDK中,为我们提供了一个管理类,它是ManagementFactory,可以在JVM启动后,获取应用的很多很多属性。例如:堆的使用情况、非堆的使用情况以及这个应用中是否发生了死锁,以及死锁的调用栈等等。那么就简单啦,在你的应用中,仅仅使用ManagementFactory就可以完美的监控一些简单的指标啦。有的人似乎在思考,如果出现OOM应该如何的监控呢?实际上,出现了OOM,此刻服务已经严重的不可用,也就是 “事中” 的阶段了,此刻不应当是监控,而是去处理这个问题以及复盘。监控的意义在于,预知的发现一些有可能导致服务不可用的因素。下面是一个发现应用中死锁的一个例子:


public class JVMTest {

    public static void main(String[] args) throws InterruptedException {
        Object a1 = new Object();
        Object a2 = new Object();
        // dead lock
        new MyThread(a1, a2).start();
        new MyThread(a2, a1).start();
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        while (true) {
            TimeUnit.SECONDS.sleep(1);
            long[] monitorDeadlockedThreads = threadMXBean.findMonitorDeadlockedThreads();
            if (null != monitorDeadlockedThreads) {
                for (long threadId : monitorDeadlockedThreads) {
                    ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
                    System.out.println(threadInfo.getThreadName());
                    System.out.println(threadInfo.getThreadId());
                    System.out.println(threadInfo.getBlockedTime());
                    StackTraceElement[] stackTrace = threadInfo.getStackTrace();
                    for (StackTraceElement stackTraceElement : stackTrace) {
                        System.out.println(stackTraceElement);
                    }
                }
            }

        }
    }

    static class MyThread extends Thread {
        Object a1, a2;

        public MyThread(Object a1, Object a2) {
            this.a1 = a1;
            this.a2 = a2;
        }

        public void run() {
            synchronized (a1) {
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a2) {
                    System.out.println("Okkk");
                }
            }
        }
    }
}

4.总结

本文中,简单的介绍了一个JVM使用量的如何监控。如果想要更加完美的平台,可以考虑使用Elasticsearch+Grafana的方式实现,都是开源免费的一些组件。同时Grafana也提供了一些事前的报警行为。

本文根据作者的一些经验书写而成,其中不乏会有一些不正确的地方,望批评指正。


程序员冈刀,目前就职于美团,java开发工程师,研究生。2022年,毕业于北京邮电大学电子工程学院、电子与通信工程专业。个人公众号《代码废柴》欢迎关注。

个人公众号