vlambda博客
学习文章列表

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

Profiling and Logging

在上一章中,我们深入探讨了多线程和并发编程的细节。我们查看了 java.util.concurrent 包 API。本章涵盖了异步编程的线程池、Spring 任务执行、调度和 Spring Async API。在本章的后半部分,我们将 Spring Async 与 CompletableFuture 进行了比较。

同样,本章将重点介绍分析和日志记录。本章首先定义分析和日志记录,以及它们如何用于评估应用程序性能。在本章的后半部分,重点将放在学习可用于研究应用程序性能的软件工具上。

本章将涵盖以下主题:

  • Performance profiling
  • Application logging and monitoring
  • Profiling tools

Performance profiling

本节将重点介绍性能测量的性能和应用程序分析。分析是任何应用程序开发和部署生命周期中的重要步骤。它帮助我们执行以下两件事:

  1. Defining a benchmark for expected performance outcomes
  2. Measuring and comparing the current performance outcome against benchmarks

第二步定义了要采取的进一步行动,以便将性能提升到基准水平。

Application performance

就软件应用程序而言,性能对不同的人来说意味着不同的东西。它必须有一些上下文才能更好地理解。应用程序性能是根据两组性能指标来衡量的。应用程序用户观察或体验到的实际性能仍然是衡量应用程序性能的最重要指标之一。它包括峰值和正常负载期间的平均响应时间。与平均响应时间相关的测量包括应用程序响应用户操作(例如页面刷新、导航或按钮单击)所花费的时间。它们还包括执行某些操作(例如排序、搜索或加载数据)所花费的时间。

本节旨在为技术团队提供有关配置和内部结构的某些方面的观点,这些方面可以设置或更改以优化效果,从而提高应用程序的性能。在通常情况下,技术团队从不关注应用程序使用的内存或 CPU 利用率,除非他们遇到性能问题。应用程序事务包括应用程序每秒接收的请求、每秒数据库事务和每秒服务的页面。系统负载通常根据应用程序处理的事务量来衡量。

还有另一组测量涉及测量应用程序在执行操作时使用的计算资源。这是确定应用程序是否有足够的资源来维持给定负载的一种非常好的方法。它还有助于确定应用程序是否使用了比预期更多的资源。如果是这样,可以得出结论,应用程序在性能方面没有优化。如今,云托管应用程序很流行。在这个时代,用户对部署在云或非云基础设施上的应用程序以及本地环境具有相同的体验非常重要。

应用程序可能不需要应用程序性能监控和改进,只要它按预期执行即可。然而,作为应用程序开发生命周期的一部分,出现了新的需求,添加了新功能,并且应用程序日益复杂。这开始影响应用程序的性能,因为主要关注点仍然是新功能开发。性能达不到标准的时候会到来,因为没有人真正致力于应用程序性能增强。

Application logging and monitoring

本节重点介绍在应用程序运行时记录重要信息。它有助于从各个方面调试应用程序,我们将详细介绍。本节介绍的另一个重要方面是应用程序监控。在某些情况下,应用程序监控被认为与应用程序分析没有什么不同;这些当然是应用程序性能测量的不同方面。

Application logging

在深入了解 Java 应用程序日志记录之前,必须了解什么是日志和日志记录。 日志 是显示信息以帮助我们了解应用程序状态的语句。日志语句以特定于应用程序的格式写入日志文件中。日志语句可以包括诸如特定语句的执行日期和时间、各种变量的值以及对象的状态等信息。将日志语句写入日志文件的过程称为logging。

每个应用程序都会为各种目的生成日志。应用程序生成日志以跟踪应用程序事件,包括访问相关事件、登录和注销事件、应用程序中发生错误时的事件以及系统配置修改。操作系统也会产生日志文件。可以处理日志文件以划分所需信息。日志记录是软件应用程序最基本的部分之一。编写良好的日志和设计良好的日志记录机制成为开发人员和管理员的巨大实用程序。它对从事应用程序支持活动的团队最有用。好吧,设计的日志记录为开发和支持团队节省了大量时间。随着前端程序的执行,系统以不可见的方式构建日志文件。

以下是常见的日志文件,通常在应用程序中生成:

  • Error/Exception logs: Any unexpected situation in an application flow is termed as an error. Errors may occur for different reasons. Errors are categorized based on severity and impact on the application. If the user cannot proceed further in the application, such an error is categorized as a blocker. If the web page does not have an appropriate label, it is categorized as a low severity issue. An error log is a recording of critical errors that have occurred while the application is executing. An application without errors virtually doesn't exist. In Java, it is not required to log all exceptions. Java supports managed exceptions, which can be taken care of and thrown as a warning or error message to the user. This could be a validation error or a user input error, which can be thrown using managed exceptions.
  • Access logs: At an abstract level, any request that comes to a web application can be considered a request to access a resource on the web application server. The resource could be a web page, a PDF file on the server, an image file, or a report from the data in the database. From a security point of view, every resource must be protected by access rights. Access rights define who can access the resource from the web application. Access logs are written information on who tried to access which resource. They may also include information about the location from which the resource was accessed. Access logs write access information for every request coming into the web application. Access logs can also be used to find information about the number of visitors, the number of visitors accessing the application for the first time, the number of visitors from a specific location, the number of requests for a particular page, and the application usage patterns.
  • Transaction logs: Transactions are related to databases. A sequence of database commands or statements executed in order to maintain atomicity and database integrity is known as a transaction. Transactions are maintained to guarantee protection over crashes or failures. A transaction log is a file where all such transactions are recorded or written. At a particular time, if the database is found to be inconsistent, then transaction logs become helpful in debugging the issue. Transaction logs can also be used to record any rollback operations performed. Usually, transaction logs also record the time of database statements to execute, along with passed in parameters. This information is very helpful in profiling database performance issues.
  • Audit logs: Auditing is the process of inspecting how the application is used. It inspects the application resources being used, the users who access or use application resources, and the authentication and authorization information for the users. The audit log records every event that the application passes through, along with the previously mentioned details.

Logging best practices

在描述了应该记录的内容和常见的日志信息之后,本节详细介绍了日志记录的最佳实践:

  • It is very important to assign appropriate log levels to each of the log statements.
  • Logging should also be considered in a cluster environment. We can use the same type of log files, with the cluster node name as a suffix to the filename. This will prevent the log entries from being overwritten or wrongly considered when analyzing logs.
  • Building log files impacts the application's performance. If an application starts logging every minor piece of information, the application's performance will be slow. We must ensure that the size of the log files and frequency of writing log entries are low.
  • All exceptions, except for validations and input errors, must be logged. The exception messages must be logged in a way that highlights the problems clearly. The best practice is to let the framework log all of the exceptions.
  • Logs must be user-friendly and easily parsed. Logs can be used in two ways. One way is that the users read the logs to build understanding. Another way is that the utility programs parse the application logs, based on the log formats, to filter out unimportant information.
  • Every log entry must be different from other log entries, though they represent the same information. Every log entry can have a unique identifier, most often based on the timestamp, which can be used to differentiate it from other logs.
  • Sensitive information must not be logged in log files. Passwords, credentials, and authentication keys are a few examples.

在大多数情况下,最佳实践作为一般指导方针,可以根据项目以定制的方式遵循。

Logging tools

在本章的前几节中,我们了解了日志记录的重要性。我们还学习了日志记录最佳实践。现在是时候将日志工具添加到我们的技能集中了。本节重点介绍日志记录工具。日志工具之所以有用,是因为它们提供的功能。过去,日志文件由以纯文本格式编写的日志语句组成。纯文本日志文件在特定情况下仍然有用,例如分析基础设施数据,但它们不再足以记录应用程序的信息。 Java 在 java.util.logging API 中内置了对标准日志记录的支持。 Log4j 是 Java 社区中另一个知名且广泛使用的日志记录工具。

在我们进入日志工具的细节之前,了解日志机制的关键元素很重要。以下是关键的日志记录组件:

  • 日志级别:Java 日志级别用于控制日志输出。它们提供了启用或禁用各种日志记录级别的灵活性。这使得可以选择将在日志文件中显示的日志。这样,在生产环境中运行的应用程序可能具有与在登台环境中运行的相同应用程序不同的日志记录级别。启用一个级别的日志记录将使所有更高级别的日志都启用以在日志文件中打印。以下是 Java 日志 API 的日志级别和有效日志级别:

    请求级别

    有效的日志记录级别

    严重

    警告

    信息

    配置

    很好

    更精细

    最好的

    严重

    是的

    是的

    是的

    是的

    是的

    是的

    是的

    警告

    没有

    是的

    是的

    是的

    是的

    是的

    是的

    信息

    没有

    是的

    是的

    是的

    是的

    是的

    配置

    没有

    没有

    没有

    是的

    是的

    是的

    是的

    很好

    没有

    没有

    没有

    没有

    是的

    是的

    是的

    更精细

    没有

    没有

    没有

    没有

    没有

    是的

    是的

    最好的

    没有

    没有

    没有

    没有

    是的

  • Logger:Logger 对象的工作是记录应用程序消息。应用程序可以创建匿名记录器,它们的存储方式与 Logger 命名空间不同。应用程序必须确保保留对 Logger 对象的引用,因为 Logger 可能会在任何时间点被垃圾收集。 Logger 对象与父 Logger 对象相关联,该对象是 Logger 命名空间中最近的祖先。在记录过程中,日志消息被发送到 Handler 对象。 Handler 对象将日志消息转发到文件、日志或控制台。每个 Logger 对象都有一个与之关联的日志级别。它表示 Logger 将为其打印日志的最低级别。

  • Handler:Handler 对象的职责是从Logger 对象获取日志消息,并将这些日志消息发送到适当的目的地进行打印。示例包括在控制台上写入日志消息、将日志消息写入文件或将日志消息写入网络日志服务。可以启用或禁用 Handler,它实质上会停止在输出介质上打印这些日志。

  • Formatter:日志Formatter在将日志消息写入输出介质之前对其进行格式化。 Java 支持两种类型的 Formatter 对象:SimpleFormatterXMLFormatterXMLFormatter 对象需要在格式化记录周围包含头部和尾部。也可以创建自定义 Formatter 对象。

  • LogManager: LogManager 是一个单例对象,用于维护记录器和日志服务的共享状态。除此之外,LogManager 对象管理日志属性和 Logger 命名空间。 LogManager 对象在类初始化发生时被实例化。该对象不能随后更改。 LogManager默认从lib/logging.properties文件中读取初始配置,可以修改。

下图显示了使用一个 Handler 的日志记录过程:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

下图显示了具有多个处理程序的日志记录过程:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

Java standard logging

本节介绍 Java 的内置日志记录机制。 Java 日志记录 API 由 java.util.logging 包组成。核心包支持将纯文本或 XML 日志条目写入输出流、文件、内存、控制台或套接字。日志 API 还能够与操作系统上现有的日志服务进行交互。

以下代码示例用于使用标准日志记录 API 打印日志消息:

package com.packt.springhighperformance.ch9.logging;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class SampleLoggingOne {
  private static Logger logger = 
  Logger.getLogger("com.packt.springhighperformance.ch4.logging");

  public static void main(String argv[]) throws SecurityException, 
  IOException {
    FileInputStream fis = new FileInputStream("D:\\projects\\spring-    
    high-performance\\SampleProject\\src\\main\\resources
    \\logging.properties");
    LogManager.getLogManager().readConfiguration(fis);
    Timestamp tOne = new Timestamp(System.currentTimeMillis());
    for(int i=0; i < 100000; i++) {
        logger.fine("doing stuff");
    }
    Timestamp tTwo = new Timestamp(System.currentTimeMillis());
    System.out.println("Time: " + (tTwo.getTime() - tOne.getTime()));
    try {
      Bird.fly();
    } catch (Exception ex) {
      logger.log(Level.WARNING, "trouble flying", ex);
    }
    logger.fine("done");
  }
}

以下是前面代码示例中引用的 logging.properties 文件的示例:

# Logging
handlers = java.util.logging.ConsoleHandler
.level = ALL

# Console Logging
java.util.logging.ConsoleHandler.level = ALL

以下是执行上述示例后的输出:

Feb 19, 2018 12:35:58 AM com.packt.springhighperformance.ch9.logging.SampleLoggingOne main
FINE: doing stuff
Feb 19, 2018 12:35:58 AM com.packt.springhighperformance.ch9.logging.SampleLoggingOne main
FINE: done

使用 Java 标准日志记录的好处是您不需要在项目中安装单独的 JAR 依赖项。尽管日志记录与我们在服务器上遇到的故障排除问题有关,但我们还必须确保日志记录不会对应用程序性能产生负面影响。必须注意以下几点以确保日志记录不会影响应用程序性能:

  • Logger.log methods are used to print log records on the output medium via a Handler. We can use Logger.isLoggable to ensure that Logger is enabled for the log level. If we pass a custom object as an argument to the Logger.log method, the toString method of the custom object is called from deep inside of the library classes. So, if we want to perform heavy operations in order to prepare an object for logging, we should do that from either within the block which checks Logger.isLoggable, or from within the object's toString method.
  • 我们不能在任何对象上调用 toString 方法来获取日志消息内容。我们也不能将 toString 方法调用作为参数传递给 Logger.logLogger 对象和日志框架负责在自定义对象上调用 toString 方法。

  • 必须避免混合使用格式字符串连接和日志参数。有错误意图的应用程序用户可能会破坏日志并使用恶意连接字符串访问用户不允许的数据。

Java 标准日志记录的主要缺点之一是比较性能。与其他基于 Java 的日志记录框架(如 Apache Log4j 2、commons logging 或 Simple Logging Facade for Java (SLF4J))相比,标准日志记录需要更多时间。

Apache Log4j 2

Apache Log4j 是 Java 社区中使用最广泛的日志框架之一。它是用 Java 编写的,并在 Apache 软件许可下分发。 Apache Log4j 2 是早期版本的修订版。最显着的特性包括线程安全、性能优化、命名记录器层次结构和国际化支持。

为了设置 Log4j 2,必须在 Maven pom.xml 文件中添加以下 Maven 依赖项:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.7</version>
</dependency>

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.7</version>
  <type>test-jar</type>
  <scope>test</scope>
</dependency>

为了访问测试命名配置文件所需的上下文规则,我们必须包含 test JAR 以及主 log4j-core 包。

Log4j 2 具有三个主要的日志记录组件:

  • Loggers: The Loggers are responsible for capturing logging information.
  • Appenders: These are similar to that of the Handler objects in Java standard logging. Appenders are responsible for broadcasting logging information or messages to configured output mediums.
  • Layouts: The Layouts are responsible for formatting the log messages into configured styles.

以下是 log4j2.xml 文件的示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT">
      <PatternLayout pattern="%d [%t] %-5level %logger{36} - %msg%n%throwable" />
    </Console>
  </Appenders>
  <Loggers>
    <Root level="ERROR">
      <AppenderRef ref="ConsoleAppender" />
    </Root>
  </Loggers>
</Configuration>

以下是 Log4j 2 Java 代码的示例:

package com.packt.springhighperformance.ch9.logging;

import org.apache.log4j.Logger;

public class SampleLog4j2Example {
  private static Logger logger = 
  Logger.getLogger(SampleLog4j2Example.class);

  public static void main(String argv[]) {
    logger.info("example info log");
    try {
      Bird.fly();
    } catch (Exception ex) {
      logger.error("example error log", ex);
    }
    logger.warn("example warning log");
  }
}

当我们执行前面的示例时,会产生以下输出:

2018-02-22 01:18:09 INFO SampleLog4j2Example:9 - example info log
2018-02-22 01:18:09 WARN SampleLog4j2Example:15 - example warning log

Apache Log4j 2 除了常见的日志级别之外,还有其他日志级别。这些是 ALLOFF 级别。当我们想要在 ALL 日志级别启用日志时,使用 ALL 日志级别。如果配置了 ALL 日志级别,则不考虑级别。 OFF 日志级别与 ALL 日志级别相反。它禁用所有日志记录。

Application monitoring

如前所述,应用程序性能被认为是任何软件应用程序生命周期中最重要的里程碑之一。还要求应用程序始终如一地执行良好。这是我们可以确保应用程序用户在应用程序中获得最佳体验的方法之一。这也意味着应用程序已启动并运行良好。应用程序性能监控工具跟踪进出应用程序的每个请求和响应,处理来自请求的信息,并在图形用户界面中进行响应和显示。这意味着监控工具为管理员提供了快速发现、隔离和解决影响性能的问题所需的数据。

监控工具通常收集有关 CPU 利用率、内存要求、带宽和吞吐量的数据。可以有多个监控系统用于不同的监控。任何应用程序性能监控的重要方面之一是将来自此类监控系统的数据组合到统计分析引擎中并将其显示在仪表板上。仪表板可以轻松读取数据日志以进行分析。应用程序监控工具可帮助管理员监控应用程序服务器,以遵守 服务水平协议 (SLA)。业务规则设置为在出现问题时向管理员发送警报。这可确保以更高的优先级考虑业务关键功能和应用程序。随着环境的快速变化,在生产系统中进行快速部署变得非常重要。快速部署意味着有更多机会引入影响系统架构的错误或减慢系统速度。

基于这些基本概念,可以使用许多实现和工具。应用程序监控工具市场巨大而拥挤,包括 AppDynamics、New Relic 和 Dynatrace 等行业领先和知名的工具。除了这些已知的工具之外,还存在开源应用程序监控工具。开源工具包括 Stagemonitor、Pinpoint、MoSKito、Glowroot、Kamon 等等。我们将在以下部分详细介绍这些工具中的每一个。

Stagemonitor

Stagemonitor 有一个监控代理,支持集群应用程序堆栈。该工具的目的是监视在许多服务器上运行的应用程序,这是一种常见的生产场景。 Stagemonitor 针对与时间序列数据库的集成进行了优化。它针对时间序列数据管理进行了优化,其中包括按时间索引的数字数组。此类数据库包括 elasticsearch、graphite 和 InfluxDB。 Stagemonitor 也可以设置在专用网络中。它使用开放式跟踪 API 来关联分布式系统中的请求。它具有定义指标的阈值。 Stagemonitor 还支持创建新插件和集成第三方插件。

Stagemonitor 包含一个基于 Java 的代理。代理位于 Java 应用程序中。代理连接到中央数据库并发送指标和请求跟踪和统计信息。 Stagemonitor 需要一个实例来监控所有应用程序、实例和主机。

在浏览器中,在监控端,我们可以看到来自集群的历史或当前数据。我们还可以创建自定义警报。也可以为每个指标定义一个阈值。 Stagemonitor 有一个仪表板。仪表板用于可视化和分析不同的指标和感兴趣的请求。 Stagemonitor 支持创建自定义仪表板、编写自定义插件和使用第三方插件。它也具有浏览器内小部件支持。该小部件不需要后端,并且会自动注入到受监控的网页中。

以下是 Stagemonitor 仪表板的屏幕截图以供参考:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

The Stagemonitor dashboard view (source: http://www.stagemonitor.org/)

Pinpoint

Pinpoint 与 Stagemonitor 的不同之处在于,它的开发考虑了大规模应用。它是在 Dapper(由 Google 开发的分布式系统跟踪基础设施)之后开发的,目的是为开发人员提供有关复杂分布式系统行为方式的更多信息。

Pinpoint 有助于分析整个系统结构以及系统的不同组件如何相互连接。 Pinpoint 通过跨分布式应用程序跟踪事务来做到这一点。它旨在解释每个事务是如何执行的,跟踪组件之间的流程以及潜在的瓶颈和问题区域。

Pinpoint 与 Stagemonitor 类似,具有用于可视化的仪表板。仪表板有助于可视化组件之间的互连。仪表板还允许用户在特定时间点监视应用程序中的活动线程。 Pinpoint 具有跟踪请求计数和响应模式。这有助于识别潜在问题。它支持查看关键信息,包括 CPU 利用率、内存利用率、垃圾收集和 JVM 参数。

Pinpoint 由四个组件组成,分别命名为 Collector、Web、Sample TestApp 和 HBase。我们可以通过分别为每个组件执行脚本来运行实例。

以下是 Pinpoint 仪表板供参考:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

The Pinpoint dashboard reference view (source: http://www.testingtoolsguide.net/tools/pinpoint-apm/)

MoSKito

MoSKito 是一组三个工具:

  • MoSKito-Essential: This standalone project is the core of MoSKito. It makes it possible to monitor the application.
  • MoSKito-Central: This works as a centralized storage server. It stores all of the performance-related information.
  • MoSKito-Control: This tool works for multi-node web applications. It provides support for monitoring multi-node web applications.

为了设置 MoSKito,我们需要在应用程序的 WEB-INF/lib 目录中安装一个 JAR 文件,该目录是保存 API 库的常用文件夹。也可以通过在 web.xml 文件中添加一个新部分来设置它。

该工具能够收集所有应用程序性能指标,包括内存、线程、存储、缓存、注册、支付、转换、SQL、服务、负载分布等等。它不需要用户在应用程序中进行任何代码更改。它支持所有主要的应用服务器,包括 Tomcat、Jetty、JBoss 和 Weblogic。它在本地存储数据。

MoSKito 还具有通知功能,可在达到阈值时广播警报。它还记录用户的操作,这可能对监视目的感兴趣。 MoSKito 提供了一个移动应用程序,用于随时随地监控应用程序。它还具有基于 Web 的仪表板。

MoSKito 的一大特色是它非常稳定并且在 Java 社区中广为人知。它得到社区和团队的支持,其中也包括付费支持。

以下是 MoSKito 仪表板供参考:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

The MoSKito dashboard view (source: https://confluence.opensource.anotheria.net/display/MSK/Javaagent+light+and+multiple+java+processes)

Glowroot

Glowroot 是一种快速、干净且简单的应用程序性能监控工具。它具有允许跟踪缓慢请求和错误的功能。使用 Glowroot,还可以记录每个用户操作所花费的时间。 Glowroot 支持 SQL 捕获和聚合。具有保留配置的数据历史汇总是 Glowroot 提供的附加功能之一。

Glowroot 支持在图表中可视化响应时间细分和响应时间百分位数。它具有响应式用户界面,允许用户使用移动设备以及桌面系统监控应用程序,而无需任何额外的安装。

Glowroot 包含在一个 ZIP 文件包中。为了开始使用 Glowroot,我们必须下载并解压缩 ZIP 文件包。 Glowroot 需要更改应用程序的 JVM 参数。我们必须在应用程序的 JVM 参数中添加 -javaagent:

一旦设置和运行,Glowroot 就会提供带有过滤功能的连续分析。我们还可以为响应时间百分比和 MBean 属性设置警报。 Glowroot 还支持跨多个线程的异步请求。在应用服务器方面,Glowroot 支持 Tomcat、Jetty、JBoss、Wildfly 和 Glassfish。

以下是 Glowroot JVM 仪表板供参考:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录
The Glowroot JVM dashboard view (source: https://demo.glowroot.org)

New Relic

New Relic 是 Java 社区中另一个广泛使用的应用程序性能监控工具。 New Relic 为应用程序和网络性能统计提供分组视图。这有助于快速诊断域级别的问题。它还提供用于深入了解特定请求的功能,以按响应时间、数据传输大小和吞吐量查看性能指标。

New Relic 支持使用 Java、Scala、Ruby、Python、PHP、.NET 和 Node.js 开发的应用程序。 New Relic 提供了四种不同的后端监控方法:

  • Application performance management: In application performance management, New Relic features high-level metrics with the ability to drill down to the code level to see how the application is performing. On the dashboard, New Relic displays a response time graph. New Relic uses the Apdex index score method to distill metrics into performance indicators. New Relic requires the user to manually set the threshold values.
  • Server monitoring: New Relic focuses on the hardware the application servers are running on. The measurements include CPU usage, memory utilization, disk I/O, and network I/O. New Relic provides brief details on the heap memory and garbage collection attributes.
  • Database monitoring: In New Relic, the dashboard for the database is a part of the application performance management dashboard. It is possible to view database monitoring metrics through plugins.
  • Insights and analytics: New Relic has a built-in, opt-in database, which stores statistics and enables querying the database.

以下是 New Relic 仪表板供参考:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

The New Relic dashboard view (source: https://newrelic.com/)

Profiling tools

分析工具或分析器是应用程序开发人员用来调查和识别代码特征和问题的软件工具。分析工具在识别性能问题方面也很有用。分析工具回答诸如设置了哪些 JVM 参数、堆内存的状态是什么、内存利用率的基于代的分类是什么、哪些线程处于活动状态等问题。一些分析器还跟踪代码中的方法,以了解 SQL 语句的调用频率或 Web 服务的调用频率。

与应用程序性能监控工具类似,市场上有许多分析工具。 VisualVM、JConsole 和 HeapAnalyzer 就是其中的一些。我们将在以下部分详细讨论每个分析工具。

VisualVM

VisualVM 是一个 Java 分析和性能分析工具。它有一个可视化界面来分析在 JVM 上本地和远程环境中运行的 Java 应用程序的详细信息。它集成并利用了 JDK 提供的命令行工具,如 jstackjconsolejmapjstatjinfo。这些工具是标准 JDK 发行版的一部分。 VisualVM 有助于解决运行时问题,具有堆转储和线程分析等功能。它有助于确定应用程序性能以及它与基准的对比。它还有助于确保最佳内存使用。它还有助于监控垃圾收集器、分析 CPU 使用情况、分析堆数据和跟踪内存泄漏。以下是 VisualVM 使用的每个命令行工具的用途:

  • jstack: This tool is used to capture the thread dumps of a Java application
  • jmap: This tool prints shared object memory maps and heap memory details for a given process
  • jstat: This tool displays performance statistics for JVMs running the application
  • jinfo: This tool prints Java configuration information

VisualVM 是标准 JDK 包的一部分。它首先在 JDK 版本 6 更新 7 中与 JDK 平台捆绑在一起。它也可以单独安装。让我们详细看看每个部分:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录
The Applications window view of VisualVM

从前面的截图可以看出,在窗口的左侧,有一个 Applications 窗口。 Applications 窗口有节点和子节点。可以展开节点和子节点以查看配置的应用程序和保存的文件。我们可以通过右键单击节点并从出现的弹出菜单中选择项目来查看其他信息或执行操作。弹出菜单选项因所选节点而异。

Applications 窗口内,我们可以看到 Local 节点的菜单。本地节点显示有关进程名称和与 VisualVM 在同一台机器上运行的 Java 进程的进程标识符的信息。启动 VisualVM 后,本地节点会在 Local 根节点展开时自动填充。 VisualVM 始终作为本地节点之一加载。服务终止时节点自动消失。如果我们获取应用程序的线程转储和堆转储,它们会像子节点一样显示。

可以使用 VisualVM 连接到在远程机器上运行的 JVM。所有此类正在运行的进程或应用程序都显示在 Remote 节点下。与远程节点建立连接后,我们可以展开 Remote 节点来查看远程机器上运行的所有 Java 应用程序。

VM Coredumps 节点仅在应用程序在 Linux 或 Solaris 操作系统上运行时可见。在 VisualVM 中打开核心转储文件时,VM Coredumps 节点会显示打开的核心转储文件。它是一个二进制文件,包含有关机器运行时状态的信息。

Applications 窗口的最后一部分标记为 SnapshotsSnapshots 部分显示应用程序运行时拍摄的所有已保存快照。

本地或远程应用程序的数据显示在 VisualVM 的选项卡中。查看应用程序数据时,默认打开 Overview 选项卡。 Overview 选项卡显示信息,包括进程 ID、系统位置、应用程序的主类、Java 安装路径、传递的 JVM 参数、JVM 标志和系统属性。

列表中的下一个选项卡是 Monitor 选项卡。 Monitor 选项卡可用于查看堆内存、永久代堆内存以及类和线程数的实时信息。这里的类表示加载到虚拟机中的类。应用程序监控过程的开销很低。

Monitor 选项卡上的堆图显示总堆大小和当前使用的堆大小。永久代区域在一段时间内的变化显示在 PermGen 图中。类图显示加载和共享类的总数。 Threads 部分显示了活动线程和守护线程的数量信息。 VisualVM 可用于进行线程转储,它显示特定时间线程的准确信息。

Monitor 选项卡中,我们可以强制执行垃圾收集。该操作将立即运行垃圾收集。也可以从 Monitor 选项卡捕获堆转储:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

VisualVM 在 Threads 选项卡中显示实时线程活动。默认情况下,Threads 选项卡显示当前线程活动的时间线。通过单击特定线程,我们可以在 Details 选项卡中查看有关该特定线程的详细信息。

Timeline 部分显示具有实时线程状态的时间线。我们可以通过在下拉菜单中选择适当的值来过滤显示的线程类型。在前面的屏幕截图中,它显示了 Live threads 时间线。我们还可以通过从下拉菜单中选择它来查看所有线程或已完成的线程。

我们可以选择在应用程序运行时对应用程序进行线程转储。打印时,线程转储显示了一个线程堆栈,其中包括 Java 应用程序的线程状态。

Profiler 选项卡可以启动和停止应用程序的分析会话。结果显示在 Profiler 选项卡本身中。可以为 CPU 分析或内存分析进行分析。启动分析会话后,VisualVM 连接到应用程序以开始收集分析数据。一旦结果可用,它们会自动显示在 Profiler 选项卡中。

JConsole

JConsole 是另一个 Java 分析工具。它编译为 Java 管理扩展 (JMX) 规范。 JConsole 广泛使用 JVM 中的检测来收集和显示有关在 Java 平台上运行的应用程序的性能和资源消耗的信息。 JConsole 在 Java SE 6 中更新为 GNOME 和 Windows 外观。

与 VisualVM 类似,JConsole 与 Java 开发工具包捆绑在一起。 JConsole 的可执行文件可以在 JDK_HOME/bin 目录中找到。可以使用以下命令从命令提示符或控制台窗口启动 JConsole:

jconsole

执行上述命令后,JConsole 会向用户显示系统上运行的所有 Java 应用程序的选择。我们可以选择连接到任何正在运行的应用程序。

如果我们知道希望 JConsole 连接到的 Java 应用程序的进程 ID,也可以提供进程 ID。以下是启动 JConsole 的命令,并连接到由其进程 ID 标识的特定 Java 应用程序:

jconsole <process-id>

以下命令可用于连接到远程机器上运行的 Java 应用程序:

jconsole hostname:portnumber

JConsole 在以下选项卡中显示信息:

  • Overview: This tab displays information about the JVM and values to be monitored. It presents the information in a graphical monitoring format. The information contains overview details on CPU usage, memory usage, thread counts, and the number of classes loaded in JVM.
  • Memory: This tab displays information about memory consumption and usage. The memory tab contains a Perform GC button, which can be clicked to activate immediate garbage collection. For the HotSpot Java VM, the memory pools are Eden Space, Survivor Space, Tenured Generation, Permanent Generation, and Code Cache. It is possible to display various charts for depicting the consumption of memory pools.
  • Threads: This tab displays information about thread usage. The threads include active threads, Live threads, and all threads. The chart's representation shows the peak number of threads and the number of live threads on two different lines. MXBean provides other information not covered by the Threads tab. With MXBean, it is possible to detect deadlocked threads.
  • Classes: This tab displays information about classes loaded in the Java virtual machine. The class information includes the total number of classes loaded so far, including those which are unloaded later on and the current number of classes loaded.
  • VM: This tab displays statistical information about the Java virtual machine. The summary includes uptime, indicating the amount of time since the JVM started; the process CPU time, indicating the amount of CPU time that JVM has consumed since it started; and the total compile time, indicating the time spent on the compilation process.
  • MBeans: This tab displays information about MBeans. The MBeans include those currently running. We can get MBeanInfo descriptor information by selecting the MBean.

以下屏幕截图显示了 JConsole 仪表板的外观:

读书笔记《hands-on-high-performance-with-spring-5》分析和记录

Summary

这一章充满了关于应用程序性能测量技术的信息。本章对于从事应用程序性能增强任务的开发团队很有用。同时,技术团队可以参考它来设置他们的应用程序日志机制。

章节从性能分析和日志的介绍性细节开始。继续前进,我们了解了特定的应用程序性能监控和应用程序日志记录。我们了解了日志记录的关键要素是什么。我们还研究了日志工具,例如标准 Java 日志和 Log4j。在本章的后半部分,我们了解了 VisualVM 作为性能分析工具。 VisualVM 是最广泛使用的基于 Java 的性能分析工具之一,可作为标准 Java 分发包提供。这就是本章的内容。

下一章将重点关注优化应用程序性能。在进行性能优化时,可以在下一章中利用本章提供的知识和信息。本章为下一章提供了基础。下一章将详细介绍如何识别性能问题的症状、性能调整生命周期以及 Spring 中的 JMX 支持。非常令人兴奋的东西,不是吗?