Tomcat 性能监控指南

应用程序服务器监控指标和运行时特性对于在每台服务器上运行的应用程序至关重要。此外,监控可以及时预防或解决潜在问题。就 Java 应用程序而言,Apache Tomcat是最常用的服务器之一。Tomcat 性能监控可以使用 JMX bean 或MoSKitoJavaMelody等监控工具来完成。

了解与监控相关的内容以及被监控指标的可接受值非常重要。在本文中,您将了解:

  • 如何设置 Tomcat 内存监控
  • 可以使用哪些指标来密切关注 Tomcat 性能

Tomcat 性能指标

在检查应用程序性能时,有几个区域可以提供有关一切是否在理想参数范围内工作的线索。以下是您需要监控的一些关键领域:

内存使用情况

此读数至关重要,因为堆内存不足会导致应用程序执行速度变慢。它甚至会导致 OutOfMemory 异常。此外,使用尽可能少的可用内存可以减少您的内存需求并最大限度地降低成本。

垃圾收集

您必须确定运行垃圾收集的正确频率,因为这是一个资源密集型过程。此外,您需要查看是否已释放足够数量的内存。

线程使用

同时有太多活动线程会减慢应用程序或整个服务器的速度。

请求吞吐量

请求吞吐量衡量服务器在特定时间单位内可以处理的请求数量,并有助于确定您的硬件需求。

会话数

与请求吞吐量类似的度量,该指标确定服务器在给定时间可以支持的会话数。

响应时间

如果您的系统响应请求的时间过长,用户可能会退出,因此监控响应时间并调查响应延迟的潜在原因至关重要。

数据库连接池

监视数据连接池可以帮助确定应用程序需要的池中的连接数。

错误率

该指标有助于识别代码库问题。

正常运行时间

正常运行时间指标显示您的服务器已经运行或关闭了多长时间。

Tomcat 服务器通过为大多数这些指标提供 JMX bean 来帮助您监控性能,可以使用 Tomcat Manager 或 JavaMelody 等工具进行验证。

接下来,我们将研究 Tomcat 性能的每个方面、任何可以帮助您监控性能的 MBean 定义,以及您可以查看度量值的方法。

但首先,让我们从研究一个非常简单的应用程序开始,我们将使用它作为示例进行监控。

要监控的示例应用程序

对于此示例,我们将使用一个小型 Web 服务应用程序,该应用程序使用由 Maven 和 Jersey 构建的 H2 数据库。

该应用程序将操作一个简单的用户实体:

public class User {
    private String email;
    private String name;

    // standard constructors, getters, setters
}

定义的 REST Web 服务有两个端点,用于将新用户保存到数据库并以 JSON 格式输出用户列表:

@Path("/users")
public class UserService {
    private UserDAO userDao = new UserDAO();
    
    public UserService () {
        userDao.createTable();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response addUser(User user) {
        userDao.add(user);
        return Response.ok()
            .build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> getUsers() {
        return userDao.findAll();
    }
}

构建 REST Web 服务超出了本文的范围。有关更多信息,请查看我们关于Java Web 服务的文章。

另外,请注意本文中的示例使用 Tomcat 版本 9.0.0.M26 进行了测试。对于其他版本,bean 或属性的名称可能略有不同。

Tomcat 性能管理器

获取 MBean 值的一种方法是通过 Tomcat 附带的 Manager App。此应用程序受保护,因此要访问它,您需要首先通过在 conf/tomcat-users.xml 文件中添加以下内容来定义用户和密码:

<role rolename="manager-gui"/>
<role rolename="manager-jmx"/>
<user username="tomcat" password="s3cret" roles="manager-gui, manager-jmx"/>

可以通过 http://localhost:8080/manager/html 访问 Manager App 界面,其中包含有关服务器状态和已部署应用程序的一些最少信息。Manager App 还提供了部署新应用程序的能力。

出于性能监控的目的,Manager App 的一项有趣功能是能够检查内存泄漏。

“查找泄漏”功能将在所有已部署的应用程序中查找内存泄漏。

有关 JMX bean 的信息可以在 http://localhost:8080/manager/jmxproxy 找到。该信息为文本格式,因为它用于工具处理。

要检索有关特定 bean 的数据,您可以将参数添加到表示 bean 名称和所需属性的 URL:

http://localhost:8080/manager/jmxproxy/?get=java.lang:type=Memory&att=HeapMemoryUsage

总体而言,此工具可用于快速检查,但它有限且不可靠,因此不推荐用于生产实例。

接下来,让我们继续讨论一个提供更友好用户界面的工具。

从哪儿开始:

使用JavaMelody启用Tomcat性能监控

如果您使用的是 Maven,只需将javamelody-core依赖项添加到 pom.xml:

<dependency>
    <groupId>net.bull.javamelody</groupId>
    <artifactId>javamelody-core</artifactId>
    <version>1.69.0</version>
</dependency>

通过这种方式,您可以启用对 Web 应用程序的监控。

在 Tomcat 上部署应用程序后,您可以通过 /monitoring URL 访问监控屏幕

JavaMelody 包含有用的图表,用于显示与各种性能度量相关的信息,以及查找 Tomcat JMX bean 值的方法。

这些 bean 中的大多数是特定于 JVM 的,而不是特定于应用程序的。

让我们了解每个最重要的指标,看看有哪些 MBean 可用以及如何以其他方式监控它们。

从哪儿开始:

内存使用情况

监控已用和可用内存有助于确保服务器正常运行和获取统计信息。当系统由于内存不足而无法再创建新对象时,JVM 会抛出异常。

请注意,内存使用量的持续增加而活动级别却没有相应的增加,这表明存在内存泄漏

通常,很难为可用内存设置最小绝对值。相反,您应该基于观察特定应用程序的趋势。当然,最大值不应超过可用物理 RAM 的大小。

可以通过添加参数在 Tomcat 中设置最小和最大堆大小:

set CATALINA_OPTS=%CATALINA_OPTS% -Xms1024m -Xmx1024m

Oracle 建议为这两个参数设置相同的值以最小化垃圾回收。

要查看可用内存,您可以使用属性 HeapMemoryUsage 检查 MBean java.lang:type=Memory

MBeans 页面可通过 /monitoring?part=mbeans URL 访问。

此外,MBean java.lang:type=MemoryPool 具有显示每种堆内存类型的内存使用情况的属性。

由于此 bean 仅显示内存的当前状态,因此您可以查看 JavaMelody 的“已用内存”图表来查看一段时间内内存使用情况的演变。

在图中,您可以看到最高的内存使用读数为 292 MB,而平均分配的 1024 MB 为 202 MB,这意味着该进程有足够的可用内存。

请注意,JavaMelody 在同一个 Tomcat 服务器上运行,这对读数的影响很小。

从哪儿开始:

垃圾收集

垃圾收集是释放未使用对象以释放内存的过程。如果系统花费超过 98% 的 CPU 时间进行垃圾收集并恢复不到 2% 的堆,则 JVM 将抛出 OutOfMemoryError 并显示“GC 开销限制超出”消息。

此类错误消息通常表示内存泄漏,因此最好注意接近这些限制的值并调查代码。

要检查这些值,请查看 java.lang:type=GarbageCollector MBean,特别是 LastGcInfo 属性,该属性显示有关上次执行 GC 的内存状态、持续时间和线程计数的信息。

使用“执行垃圾收集”链接可以从 JavaMelody 触发完整的垃圾收集周期。让我们看看垃圾收集前后内存使用的演变:

在示例应用程序的情况下,GC 在 23:30 运行,图表显示很大比例的内存被回收。

从哪儿开始:

线程使用

为了查找正在使用的线程的状态,Tomcat 提供了 ThreadPool MBean。currentThreadsBusy、currentThreadCount 和 maxThreads 属性提供有关当前繁忙的线程数、当前在线程池中的线程数以及可以创建的最大线程数的信息。

默认情况下,Tomcat 使用的 maxThreads 数为 200。

如果您预计并发请求的数量会更大,您可以通过修改 conf/server.xml 文件来自然地增加计数:

<Connector port="8080" protocol="HTTP/1.1"
  connectionTimeout="20000"
  redirectPort="8443" 
  maxThreads="400"/>

或者,如果系统在线程数较多的情况下性能不佳,您可以调整该值。这里重要的是一组良好的性能测试,以将负载放在系统上,以查看应用程序和服务器如何处理该负载。

从哪儿开始:

请求吞吐量和响应时间

要确定给定时间段内的请求数,您可以使用 MBean Catalina:type=GlobalRequestProcessor,它具有 requestCount 和 errorCount 等属性,表示执行的请求总数和遇到的错误。

maxTime 属性表示处理请求的最长时间,而 processingTime 表示处理所有请求的总时间。

直接查看这个 MBean 的缺点是它包含了对服务器的所有请求。要隔离 HTTP 请求,您可以查看 JavaMelody 界面的“每分钟 HTTP 命中数”图。

让我们发送一个检索用户列表的请求,然后发送一组请求以添加用户并再次显示该列表:

您可以在图表中看到 17:00 左右发送的请求数,平均执行时间为 65 毫秒。

JavaMelody 提供有关所有请求和平均响应时间的高级信息。但是,如果您想更详细地了解每个请求,您可以添加另一个工具,例如Prefix来监控每​​个 Web 请求的应用程序性能

Prefix 的另一个优点是定位哪些请求属于哪个应用程序,以防您在同一个 Tomcat 服务器上部署了多个应用程序。

使用 JavaMelody 和前缀

为了同时使用 JavaMelody 和 Prefix,您必须禁用 JavaMelody 监控报告的 gzip 压缩以避免对所有内容进行两次编码。 

要禁用 gzip 压缩,只需将 gzip-compression-disabled 参数添加到应用程序的 web.xml 中的 MonitoringFilter 类:

<filter>
  <filter-name>javamelody</filter-name>
  <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
  <init-param>
    <param-name>gzip-compression-disabled</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

接下来,下载Prefix,然后在 Tomcat 安装的 bin 目录中创建一个 setenv.bat(Unix 系统为 setenv.sh)文件。在此文件中,将 -javaagent 参数添加到 CATALINA_OPTS 以启用 Tomcat 服务器的前缀分析。

set CATALINA_OPTS=%CATALINA_OPTS% -javaagent:"C:\Program Files (x86)\StackifyPrefix\java\lib\stackify-java-apm.jar"

现在您可以在h ttp://localhost:2012/访问 Prefix 报告,查看每个请求执行的时间以及花费了多长时间:

这对于跟踪应用程序中任何延迟的原因非常有用。

数据库连接

连接到数据库是一个密集的过程,这就是使用连接池很重要的原因。

Tomcat 通过在c onf/context.xml 文件中添加 Resource 元素提供了一种配置使用连接池的 JNDI 数据源的方法:

<Resource
  name="jdbc/MyDataSource"
  auth="Container"
  type="javax.sql.DataSource"
  maxActive="100"
  maxIdle="30"
  maxWait="10000"
  driverClassName="org.h2.Driver"
  url="jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1"
  username="sa"
  password="sa"
/>

然后MBean Catalina:type=DataSource 可以显示有关 JNDI 数据源的信息,例如 numActive 和 numIdle,表示活动或空闲连接的数量。

对于要在 JavaMelody 界面中显示的数据库连接,您需要将 JNDI 数据源命名为 MyDataSource。之后,您可以查阅“每分钟 SQL 命中数”、“SQL 平均时间”和“SQL 错误百分比”等图表。

有关发送到数据库的每个 SQL 命令的更多详细信息,您可以查阅每个 HTTP 请求的前缀。数据库图标标记涉及数据库连接的请求。

Prefix 将显示应用程序生成的 SQL 查询。让我们看看 Prefix 记录的调用 addUser() 端点方法的数据:

上面的屏幕截图显示了 SQL 代码以及执行结果。

如果出现 SQL 错误,Prefix 也会显示给您。例如,如果有人尝试使用现有电子邮件地址添加用户,则会导致违反主键约束:

该工具显示 SQL 错误消息,以及导致它的脚本。

错误率

错误表明您的应用程序未按预期执行,因此监控错误发生的速度很重要。Tomcat 没有为此提供 MBean,但您可以使用其他工具来查找此信息。

让我们通过为 JNDI 数据源编写一个不正确的名称来在示例应用程序中引入一个错误,并查看性能工具的行为方式。

JavaMelody 提供了一个“HTTP 错误百分比”图表,该图表显示了在给定时间有多少百分比的请求导致错误:

该图表向您显示发生了错误,但它对识别错误没有多大帮助。为此,您可以使用 Prefix,它会突出显示以错误代码结尾的 HTTP 请求:

如果您选择此请求,Prefix 将显示有关已访问的端点和遇到的错误的详细信息

使用 Prefix 我们看到访问 /users 端点时发生了错误,原因是“MyyyDataSource is not bound in this context”,这意味着没有找到名称不正确的 JNDI 数据源。

结论

Tomcat 性能监控对于在生产环境中成功运行 Java 应用程序至关重要。Tomcat 内存监控可确保您的应用程序响应请求而不会出现明显延迟,并识别代码中的任何潜在错误或内存泄漏。您需要这些数据来跟踪生产应用程序并主动监控可能出现的任何问题。

Tomcat 通过提供一系列可以监控的与性能相关的 JMX bean 来预见这种需求。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值