怎样监控java进程?

1问题

怎样实现对自己编写的java程序的监控?比如说想知道:

  • 请求的tps
  • jvm的内存信息,线程信息
  • 线程池的使用情况等。
  • 某段代码的执行时间

常用方法就是埋点,通过代理减小业务的侵入性(如是spring下的aop)。这种埋点一般有两种方式,

  • 直接借助第三方组件实现指标监控,如prometheus,聚合类统计指标需要自己管理实现。
  • 另一种方式是直接使用java自带的jmx。

 

2 jmx介绍

JMX 全称为 Java Management Extensions,翻译过来就是 Java 管理扩展,用来管理和监测 Java 程序。最常用到的就是对于 JVM 的监测和管理,比如 JVM 内存、CPU 使用率、线程数、垃圾收集情况等等。另外,还可以用作日志级别的动态修改,比如 log4j 就支持 JMX 方式动态修改线上服务的日志级别。最主要的还是被用来做各种监控工具,比如 Spring Boot Actuator、JConsole、VisualVM 等。更多的jmx介绍可自行搜索。
利用metrics工具包和jmx可以很方便的实现java程序的监控逻辑。
 
3 java metrics工具包
git:https://github.com/dropwizard/metrics
官网(4.2.0版本):https://metrics.dropwizard.io/4.2.0/
 
官方介绍如下:
Metrics is a Java library which gives you unparalleled insight into what your code does in production.
Metrics provides a powerful toolkit of ways to measure the behavior of critical components in your production environment.
With modules for common libraries like Jetty, Logback, Log4j, Apache HttpClient, Ehcache, JDBI, Jersey and reporting backends like Graphite, Metrics provides you with full-stack visibility.
也就是说这个工具包可以让你在生产环境中产生度量的一些数据,并且支持不同的输出方式。
 
下面示例,通过metric统计程序近1分钟,5分钟,15分钟的tps三个指标
maven pom坐标
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>4.2.16</version>
        </dependency>

测试代码如下

public class TestMetrics {
    final static MetricRegistry register = new MetricRegistry();

    public static void main(String[] args) throws Exception{
        TestMetrics testMetrics = new TestMetrics();
        testMetrics.test();
    }

    public void test() throws Exception{
        ConsoleReporter reporter = ConsoleReporter.forRegistry(register)
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .build();
        reporter.start(3, TimeUnit.SECONDS);
        Meter meter = register.meter(MetricRegistry.name(TestMetrics.class, "request", "tps"));

        while(true) {
            meter.mark();
            Thread.sleep(500);
        }
    }
}

第一步先初始化一个MetricRegistry,注册器可以全局唯一做成单例

第二步初始化Reporter用于输出指标,可以控制打印频率等。这里定义了ConsoleReporter,也就是说指标将会打到控制台,3秒输出一次。

第三步定义meter类型的指标,用于度量某个时间段的平均处理次数。

最后通过while循环模拟每500ms一个请求。

输出:

23-2-15 12:25:42 ===============================================================

-- Meters ----------------------------------------------------------------------
com.ouym.study.jmx.TestMetrics.request.tps
             count = 6
         mean rate = 1.99 events/second
     1-minute rate = 0.00 events/second
     5-minute rate = 0.00 events/second
    15-minute rate = 0.00 events/second


23-2-15 12:25:45 ===============================================================

-- Meters ----------------------------------------------------------------------
com.ouym.study.jmx.TestMetrics.request.tps
             count = 12
         mean rate = 1.99 events/second
     1-minute rate = 2.00 events/second
     5-minute rate = 2.00 events/second
    15-minute rate = 2.00 events/second


23-2-15 12:25:48 ===============================================================

-- Meters ----------------------------------------------------------------------
com.ouym.study.jmx.TestMetrics.request.tps
             count = 18
         mean rate = 1.99 events/second
     1-minute rate = 2.00 events/second
     5-minute rate = 2.00 events/second
    15-minute rate = 2.00 events/second

3秒打一次,除了第一次不准外,后面都是准确的。

当然,实际项目中我们不可能达到控制台观看,我们一般可以输出到jmx或者http,下面以reporter到jmx为例,需要引入metrics-jmx模块

       <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-jmx</artifactId>
            <version>4.2.16</version>
        </dependency>

测试代码

public class TestMetrics {
    final static MetricRegistry register = new MetricRegistry();

    public static void main(String[] args) throws Exception{
        TestMetrics testMetrics = new TestMetrics();
        testMetrics.test();
    }

    public void test() throws Exception{
        JmxReporter reporter = JmxReporter.forRegistry(register)
                .convertRatesTo(TimeUnit.SECONDS)
                .convertDurationsTo(TimeUnit.MILLISECONDS)
                .build();
        reporter.start();
        Meter meter = register.meter(MetricRegistry.name(TestMetrics.class, "request", "tps"));

        while(true) {
            meter.mark();
            Thread.sleep(500);
        }
    }
}

打开jconsole可以看到MBean

 

 

 

Metrics工具包提供了4种类型的指标,上述实例使用的是meters类型

Gauge (计量器):统计瞬时状态的数据信息。

Counter(计数器):维护一个计数,每次提交都是往上累加

Meters(度量器):度量某个时间段的平均处理次数(request per second)

Histogram(直方图):统计数据的分布情况,最大值、最小值、平均值、中位数,百分比(75%、90%、95%、98%、99%和99.9%)。

Timers(计时器):统计某一块代码段的执行时间以及其分布情况,基于Histograms和Meters来实现的。

posted @ 2023-02-15 13:41  OUYM  阅读(514)  评论(0编辑  收藏  举报