searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

系统监控和JFR

2023-08-07 02:51:16
29
0

JFR简介

Java Flight Recorder(JFR)是 JDK 7 Update 40 以后的版本中内置的一款工具,用于记录和分析 Java 应用程序的运行时信息和事件。它可以记录诸如 CPU 使用率、内存使用率、线程情况、方法调用信息、垃圾收集等重要信息,并将这些信息保存到二进制文件中。

Java Flight Recorder 的特点包括:

1. 低开销:Java Flight Recorder 通过在 JVM 中内置的事件处理器捕获事件信息,与其他监控工具相比,其性能损耗非常小。
2. 高效性:Java Flight Recorder 可以在生产环境下持续监控应用程序,不会对应用程序的性能产生明显的影响。
3. 可扩展性:Java Flight Recorder 的事件处理器是可扩展的,用户可以编写自己的事件处理器来监控应用程序的自定义事件。
4. 简单易用:Java Flight Recorder 集成在 JDK 中,不需要安装或配置其他软件,用户只需要通过命令行或图形界面就可以启动和停止监控。

Java Flight Recorder 可以用于诊断和调试 Java 应用程序的性能问题和错误,也可以用于分析和优化 Java 应用程序的运行状况。它可以帮助用户深入了解应用程序的运行情况和行为,提高应用程序的性能和可靠性。

数据获取

Java Flight Recorder 支持多种数据获取方式,包括:

1. 命令行工具:用户可以使用 jcmd 命令行工具启动和停止 Java Flight Recorder,也可以使用 jcmd 工具来导出和分析记录的数据。
2. Java Mission Control(JMC):是一款图形界面工具,用于监控和分析 Java 应用程序,也可以与 Java Flight Recorder 集成,提供了丰富的报告和分析功能。
3. API:用户可以使用 Java Flight Recorder API 编写自己的事件处理器,并与 Java Flight Recorder 集成,实现自定义事件的监控和分析。

特点

Java Flight Recorder (JFR)是一种低开销的性能监控工具,它使用的是 JDK 自身的工具链和 API,因此对程序的正常运行影响非常小。

在生产环境中,Java 应用程序通常运行在高并发和高负载的情况下,因此对应用程序的性能和可靠性要求非常高。Java Flight Recorder 在这种情况下具有很高的适用性,它可以在后台以极低的开销记录应用程序的事件,并可以随时启动和停止监控,不需要重启应用程序或暂停应用程序的运行。

Java Flight Recorder 的工作原理是通过 JVM 提供的事件流 API 来记录应用程序的事件。这个 API 使用了非常少的 CPU 资源,因此对应用程序的正常运行影响非常小。对于高并发和高负载的应用程序,Java Flight Recorder 的性能损耗通常小于 1%,因此可以在生产环境中使用。

需要注意的是,在启用 Java Flight Recorder 时,需要配置合适的事件和参数,以避免产生过多的事件和记录数据,从而导致不必要的开销。同时,也需要注意控制记录数据的大小和频率,以避免占用过多的磁盘空间或网络带宽。

应用实战

要求:请基于JAVA FLIGHT RECORDER,帮忙用代码实现对当前运行进程线程、cpu、内存、磁盘、网络读写流量和延迟,以及GC情况的历史统计,并将上述统计结果保存至MYSQL监控表中。

<dependencies>
  <dependency>
    <groupId>com.oracle</groupId>
    <artifactId>jmc</artifactId>
    <version>7.1.0</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.27</version>
  </dependency>xm
</dependencies>
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import org.openjdk.jmc.common.item.Aggregators;
import org.openjdk.jmc.common.item.IItemCollection;
import org.openjdk.jmc.flightrecorder.JfrLoader;
import org.openjdk.jmc.flightrecorder.jdk.JdkFilters;
import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs;

public class JfrToMysql {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/monitoring";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";

    public static void main(String[] args) throws Exception {
        long startTime = System.currentTimeMillis() - 60000; // 统计过去 60 秒的数据
        long endTime = System.currentTimeMillis();

        // 加载 JFR 文件
        IItemCollection items = JfrLoader.loadSync("recording.jfr", startTime, endTime);

        // 连接到 MySQL 数据库
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // 将 CPU 使用率存储到数据库
            List < Double > cpuData = items.apply(JdkFilters.CPU_LOAD).getAggregate(Aggregators.avg(JdkTypeIDs.CPU_LOAD));
            saveToDatabase(conn, "cpu_load", cpuData);

            // 将内存使用情况存储到数据库
            List < Long > memData = items.apply(JdkFilters.MEMORY_USED).getAggregate(Aggregators.avg(JdkTypeIDs.MEMORY_USED));
            saveToDatabase(conn, "memory_used", memData);

            // 将磁盘 IO 存储到数据库
            List < Double > diskData =
                items.apply(JdkFilters.IO).getAggregate(Aggregators.avg(JdkTypeIDs.IO_BYTES_WRITTEN));
            saveToDatabase(conn, "disk_io", diskData);

            // 将网络 IO 存储到数据库
            List < Double > netData =
                items.apply(JdkFilters.NETWORK).getAggregate(Aggregators.avg(JdkTypeIDs.NETWORK_BYTES_RECEIVED));
            saveToDatabase(conn, "network_io", netData);

            // 将延迟存储到数据库
            List < Long > latencyData =
                items.apply(JdkFilters.LATENCY).getAggregate(Aggregators.avg(JdkTypeIDs.LATENCY));
            saveToDatabase(conn, "latency", latencyData);

            // 将 GC 时间存储到数据库
            List < Long > gcData = items.apply(JdkFilters.GC).getAggregate(Aggregators.sum(JdkTypeIDs.GC_PAUSE));
            saveToDatabase(conn, "gc_pause", gcData);
        }
    }

    private static void saveToDatabase(Connection conn, String metricName, List << ? extends Number > data) throws SQLException {
        String sql = "INSERT INTO monitoring_data (metric_name, value) VALUES (?, ?)";
        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
            for (Number d: data) {
                stmt.setString(1, metricName);
                stmt.setDouble(2, d.doubleValue());
                stmt.addBatch();
            }
            stmt.executeBatch();
        }
    }
}

补充说明

JFR完整的监控指标,可以参照在线文档

https://bestsolution-at.github.io/jfr-doc/openjdk-11.html

 

0条评论
0 / 1000
吴****昌
4文章数
0粉丝数
吴****昌
4 文章 | 0 粉丝
吴****昌
4文章数
0粉丝数
吴****昌
4 文章 | 0 粉丝
原创

系统监控和JFR

2023-08-07 02:51:16
29
0

JFR简介

Java Flight Recorder(JFR)是 JDK 7 Update 40 以后的版本中内置的一款工具,用于记录和分析 Java 应用程序的运行时信息和事件。它可以记录诸如 CPU 使用率、内存使用率、线程情况、方法调用信息、垃圾收集等重要信息,并将这些信息保存到二进制文件中。

Java Flight Recorder 的特点包括:

1. 低开销:Java Flight Recorder 通过在 JVM 中内置的事件处理器捕获事件信息,与其他监控工具相比,其性能损耗非常小。
2. 高效性:Java Flight Recorder 可以在生产环境下持续监控应用程序,不会对应用程序的性能产生明显的影响。
3. 可扩展性:Java Flight Recorder 的事件处理器是可扩展的,用户可以编写自己的事件处理器来监控应用程序的自定义事件。
4. 简单易用:Java Flight Recorder 集成在 JDK 中,不需要安装或配置其他软件,用户只需要通过命令行或图形界面就可以启动和停止监控。

Java Flight Recorder 可以用于诊断和调试 Java 应用程序的性能问题和错误,也可以用于分析和优化 Java 应用程序的运行状况。它可以帮助用户深入了解应用程序的运行情况和行为,提高应用程序的性能和可靠性。

数据获取

Java Flight Recorder 支持多种数据获取方式,包括:

1. 命令行工具:用户可以使用 jcmd 命令行工具启动和停止 Java Flight Recorder,也可以使用 jcmd 工具来导出和分析记录的数据。
2. Java Mission Control(JMC):是一款图形界面工具,用于监控和分析 Java 应用程序,也可以与 Java Flight Recorder 集成,提供了丰富的报告和分析功能。
3. API:用户可以使用 Java Flight Recorder API 编写自己的事件处理器,并与 Java Flight Recorder 集成,实现自定义事件的监控和分析。

特点

Java Flight Recorder (JFR)是一种低开销的性能监控工具,它使用的是 JDK 自身的工具链和 API,因此对程序的正常运行影响非常小。

在生产环境中,Java 应用程序通常运行在高并发和高负载的情况下,因此对应用程序的性能和可靠性要求非常高。Java Flight Recorder 在这种情况下具有很高的适用性,它可以在后台以极低的开销记录应用程序的事件,并可以随时启动和停止监控,不需要重启应用程序或暂停应用程序的运行。

Java Flight Recorder 的工作原理是通过 JVM 提供的事件流 API 来记录应用程序的事件。这个 API 使用了非常少的 CPU 资源,因此对应用程序的正常运行影响非常小。对于高并发和高负载的应用程序,Java Flight Recorder 的性能损耗通常小于 1%,因此可以在生产环境中使用。

需要注意的是,在启用 Java Flight Recorder 时,需要配置合适的事件和参数,以避免产生过多的事件和记录数据,从而导致不必要的开销。同时,也需要注意控制记录数据的大小和频率,以避免占用过多的磁盘空间或网络带宽。

应用实战

要求:请基于JAVA FLIGHT RECORDER,帮忙用代码实现对当前运行进程线程、cpu、内存、磁盘、网络读写流量和延迟,以及GC情况的历史统计,并将上述统计结果保存至MYSQL监控表中。

<dependencies>
  <dependency>
    <groupId>com.oracle</groupId>
    <artifactId>jmc</artifactId>
    <version>7.1.0</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.27</version>
  </dependency>xm
</dependencies>
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import org.openjdk.jmc.common.item.Aggregators;
import org.openjdk.jmc.common.item.IItemCollection;
import org.openjdk.jmc.flightrecorder.JfrLoader;
import org.openjdk.jmc.flightrecorder.jdk.JdkFilters;
import org.openjdk.jmc.flightrecorder.jdk.JdkTypeIDs;

public class JfrToMysql {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/monitoring";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";

    public static void main(String[] args) throws Exception {
        long startTime = System.currentTimeMillis() - 60000; // 统计过去 60 秒的数据
        long endTime = System.currentTimeMillis();

        // 加载 JFR 文件
        IItemCollection items = JfrLoader.loadSync("recording.jfr", startTime, endTime);

        // 连接到 MySQL 数据库
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // 将 CPU 使用率存储到数据库
            List < Double > cpuData = items.apply(JdkFilters.CPU_LOAD).getAggregate(Aggregators.avg(JdkTypeIDs.CPU_LOAD));
            saveToDatabase(conn, "cpu_load", cpuData);

            // 将内存使用情况存储到数据库
            List < Long > memData = items.apply(JdkFilters.MEMORY_USED).getAggregate(Aggregators.avg(JdkTypeIDs.MEMORY_USED));
            saveToDatabase(conn, "memory_used", memData);

            // 将磁盘 IO 存储到数据库
            List < Double > diskData =
                items.apply(JdkFilters.IO).getAggregate(Aggregators.avg(JdkTypeIDs.IO_BYTES_WRITTEN));
            saveToDatabase(conn, "disk_io", diskData);

            // 将网络 IO 存储到数据库
            List < Double > netData =
                items.apply(JdkFilters.NETWORK).getAggregate(Aggregators.avg(JdkTypeIDs.NETWORK_BYTES_RECEIVED));
            saveToDatabase(conn, "network_io", netData);

            // 将延迟存储到数据库
            List < Long > latencyData =
                items.apply(JdkFilters.LATENCY).getAggregate(Aggregators.avg(JdkTypeIDs.LATENCY));
            saveToDatabase(conn, "latency", latencyData);

            // 将 GC 时间存储到数据库
            List < Long > gcData = items.apply(JdkFilters.GC).getAggregate(Aggregators.sum(JdkTypeIDs.GC_PAUSE));
            saveToDatabase(conn, "gc_pause", gcData);
        }
    }

    private static void saveToDatabase(Connection conn, String metricName, List << ? extends Number > data) throws SQLException {
        String sql = "INSERT INTO monitoring_data (metric_name, value) VALUES (?, ?)";
        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
            for (Number d: data) {
                stmt.setString(1, metricName);
                stmt.setDouble(2, d.doubleValue());
                stmt.addBatch();
            }
            stmt.executeBatch();
        }
    }
}

补充说明

JFR完整的监控指标,可以参照在线文档

https://bestsolution-at.github.io/jfr-doc/openjdk-11.html

 

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0