当前位置:Java -> 使用JMX进行调试再探讨

使用JMX进行调试再探讨

有效的调试需要细致的方法,类似于使用夹子从两侧紧紧抓住问题。虽然低级工具在系统级服务调试中有其用武之地,但今天的焦点转向开发堆栈的更复杂部分:高级管理工具。了解这些工具对开发人员至关重要,因为它填补了代码创建和操作部署之间的差距,增强了应用程序在广泛基础架构上的管理效率和效果。

开发中高级管理工具的需求

开发和DevOps团队利用一系列工具,这些工具通常被开发人员视为复杂或陌生。这些旨在可伸缩性的工具能够同时管理成千上万台服务器。尽管在较小规模情况下并不总是必要,但这种能力在应用程序管理中提供了重要的优势。高级管理工具有助于导航和控制多台机器,使其对于寻求优化应用程序性能和可靠性的开发人员至关重要。

Java管理扩展 (JMX) 简介

应用程序管理中的一个关键标准是Java管理扩展 (JMX),Java引入它来简化与应用程序的交互和管理。JMX允许应用程序和Java开发工具包 (JDK) 本身暴露关键信息和功能,使外部工具能够动态操纵这些元素。虽然 JMX 的激活超出了本讨论的范围,但它的重要性不容忽视,并且有大量资源可供那些对其实施感兴趣的人使用。

设置 JMX

JMX 默认不启用,启用它需要以下步骤:

1. 修改 JVM 启动参数

要在 Java 应用程序上启用 JMX,必须调整Java虚拟机 (JVM) 的启动参数。这涉及向应用程序的启动命令添加特定标志。启用 JMX 的基本标志包括:

  • -Dcom.sun.management.jmxremote:此标志激活了远程 JMX 管理和监控。
  • -Dcom.sun.management.jmxremote.port=<PORT>:用指定的端口号 <PORT> 替换此处,远程连接将在该端口上侦听。
  • -Dcom.sun.management.jmxremote.ssl=false:此标志禁用了 JMX 连接的 SSL。对于开发环境,为简单起见,可能会禁用 SSL,但对于生产环境,请考虑启用 SSL 以确保安全。
  • -Dcom.sun.management.jmxremote.authenticate=false:此标志禁用了身份验证。类似于SSL,开发中可以禁用身份验证,但在生产中应启用以确保安全访问。

2. 重新启动应用程序

设置了 JVM 参数后,重新启动应用程序。这将应用新的启动参数,从而激活 JMX。

3. 验证 JMX 连通性

重新启动应用程序后,可以通过使用JConsole、VisualVM或自定义管理应用程序这样的JMX客户机来验证 JMX 是否已启用。使用启动参数中指定的端口号建立连接。

JMX 安全考虑

虽然启用 JMX 提供了强大的管理能力,但关键是要考虑安全影响,尤其是当 JMX 公开在一个网络上时。在生产中部署应用程序时,务必始终启用 SSL 和身份验证以防止未经授权的访问。此外,考虑防火墙规则和网络策略,以限制 JMX 访问受信任的客户端。

理解 MBeans

JMX的核心是管理Bean (MBeans),它们是应用程序内的控制点。这些 Bean 使开发人员能够发布特定功能以进行运行时监视和配置。将应用程序指标导出到仪表板通过 MBeans 特别有价值,从而基于准确、最新的信息进行实时决策。此外,例如用户管理等操作可以通过 MBeans 公开,增强了管理功能。

Spring 和管理 Bean

Spring Framework 的 Actuator 模块典型地展现了在开发中集成管理能力,提供了广泛的指标和运营细节。这种集成推动了应用程序达到 "生产就绪" 状态,使开发人员能够以前所未有的深度和效率进行监视和管理应用程序。

JMX 管理工具

虽然 JMX 可通过各种Web界面和管理工具访问,但命令行工具提供了一种直接高效的方法,用于在生产服务器上与启用了 JMX 的应用程序进行交互。JMXTerm之类的工具通过提供快速见解的简化界面,为特别是对开发人员来说陌生的环境中提供支持,使其成为视觉工具的补充。

使用 JMXTerm 入门

JMXTerm是一个强大的实用程序,用于管理JMX,无需图形化可视化,非常适合快速诊断或高级服务器洞察。在启用JVM上的JMX并设置必要的配置后,开发人员可以连接到服务器,探索不同的JMX域,并直接从命令行操作MBeans。

我们可以通过可视工具或有时使用Web界面来完成以下所有操作。通常,这是我使用的方法。然而,作为一个学习工具,我认为JMXTerm非常棒,因为它以一种一致且冗长的方式公开了事物。如果我们能理解JMXTerm,GUI版本就会变得非常简单...

我们可以使用命令行启动JMXTerm,在我这里,我使用了以下命令:

java -jar ~/Downloads/jmxterm-1.0.2-uber.jar --url localhost:30002


一旦建立连接,我们就可以向JMX发出命令,并获取有关JVM或应用程序的信息;例如,我可以列出域,你可以将其视为类似于“包”或“模块”的方式来组织各种bean:

$>domains
#following domains are available
JMImplementation
com.sun.management
java.lang
java.nio
java.util.logging
javax.cache
jdk.management.jfr


我可以选择特定的域,从而在该域中执行未来操作:

$>domain java.util.logging
#domain is set to java.util.logging


进入域后,我可以选择特定的bean并对其执行操作。为此,我首先需要列出该域中的beans;在这种情况下,只有日志bean。然后我可以使用bean命令选择该bean:

$>beans
#domain = java.util.logging:
java.util.logging:type=Logging
$>bean java.util.logging:type=Logging
#bean is set to java.util.logging:type=Logging


我可以在beans上执行许多操作。也许最有用的是info命令,它让我查询bean。请注意,bean可以具有属性,将它们视为对象字段和操作,您可以将其视为方法。还有可以将其视为事件的通知:

$>info
#mbean = java.util.logging:type=Logging
#class name = sun.management.ManagementFactoryHelper$PlatformLoggingImpl
# attributes
  %0   - LoggerNames ([Ljava.lang.String;, r)
  %1   - ObjectName (javax.management.ObjectName, r)
# operations
  %0   - java.lang.String getLoggerLevel(java.lang.String p0)
  %1   - java.lang.String getParentLoggerName(java.lang.String p0)
  %2   - void setLoggerLevel(java.lang.String p0,java.lang.String p1)
#there's no notifications


我可以运行操作并传递各种命令;例如,我可以获取记录器级别,设置它,然后检查记录器级别是否确实已更新:

$>run getLoggerLevel "org.apache.tomcat.websocket.WsWebSocketContainer"
#calling operation getLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer]
#operation returns:
$>run setLoggerLevel org.apache.tomcat.websocket.WsWebSocketContainer INFO
#calling operation setLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer, INFO]
#operation returns: 
null
$>run getLoggerLevel "org.apache.tomcat.websocket.WsWebSocketContainer"
#calling operation getLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer]
#operation returns: 
INFO


这只是冰山一角。我们可以获得许多东西,例如Spring设置,内部VM信息等。在这个示例中,我可以直接从控制台查询VM信息:

$>domain com.sun.management
#domain is set to com.sun.management
$>beans
#domain = com.sun.management:
com.sun.management:type=DiagnosticCommand
com.sun.management:type=HotSpotDiagnostic
$>bean com.sun.management:type=HotSpotDiagnostic
#bean is set to com.sun.management:type=HotSpotDiagnostic
$>info
#mbean = com.sun.management:type=HotSpotDiagnostic
#class name = com.sun.management.internal.HotSpotDiagnostic
# attributes
  %0   - DiagnosticOptions ([Ljavax.management.openmbean.CompositeData;, r)
  %1   - ObjectName (javax.management.ObjectName, r)
# operations
  %0   - void dumpHeap(java.lang.String p0,boolean p1)
  %1   - javax.management.openmbean.CompositeData getVMOption(java.lang.String p0)
  %2   - void setVMOption(java.lang.String p0,java.lang.String p1)
#there's no notifications


在调试和管理中利用JMX

JMX具备作为管理控制台的强大工具的能力,允许开发人员公开其项目的关键设置和指标。除了其常规用途之外,JMX还可以作为调试过程的一部分,用作触发调试场景或在管理UI中观察调试会话的伪界面。这种方法不仅简化了服务器应用程序的管理,还增强了开发人员诊断和高效解决问题的能力。

在Spring Boot中暴露MBeans

到目前为止,我们讨论了处理JVM或Spring的bean的过程。但是,我们自己的应用程序逻辑呢?

我们可以公开我们自己的应用程序内部状态,以便我们(和我们的SREs)可以在生产和测试环境中对其进行审查。我们可以不再构建自定义控制面板或记录所有内容,而只需公开数据。如果某个标志有问题,我们可以在生产环境中进行更改,如果您想查询特定状态,也可以将其公开。

Spring Boot通过其对JMX的全面支持简化了应用程序的管理和监控。通过利用Spring的基础设施,我们可以轻松地将他们的应用程序bean公开为JMX管理bean(MBeans),使它们可以通过JMX客户端进行监视和管理。

了解Spring Boot JMX支持

Spring Boot会为您自动配置JMX,并公开使用@ManagedResource注解的任何bean作为JMX MBeans。此功能与Spring Boot的Actuator结合使用,提供了丰富的管理端点集,涵盖了从指标到线程转储的应用程序的各个方面。

在Spring Boot中公开MBean

要公开一个bean,需要执行以下步骤:

1. 定义管理接口

创建一个定义要通过JMX公开的操作和属性的接口。此接口应该使用JMX注解进行注释,例如@ManagedOperation用于方法和@ManagedAttribute用于字段或getter/setter方法。

2. 实现MBean

在执行实际操作和定义的属性的类中实现接口。这个类代表您的MBean,并且可以是一个常规的由Spring管理的bean。

3. 使用@ManagedResource对Bean进行注释

使用@ManagedResource对MBean实现类进行注释,以指示它应该作为MBean公开。您可以在此注释中为MBean指定对象名称,在JMX客户端中将其识别为该名称。

4. 在Spring Boot中启用JMX

确保在Spring Boot应用程序中启用了JMX。这通常是默认行为,但您可以在application.propertiesapplication.yml文件中设置spring.jmx.enabled=true来显式启用。

5. 通过JMX客户端访问MBean

一旦您的应用程序运行,您可以通过任何标准的JMX客户端(例如JConsole、VisualVM或自定义客户端)访问公开的MBean。连接到Spring Boot应用程序的JMX域,您会找到您公开的MBean,可以进行交互。

示例:公开一个简单的配置MBean

// Define a management interface
public interface ConfigurationMBean {
    @ManagedAttribute
    String getApplicationName();

    @ManagedOperation
    void updateApplicationName(String name);
}

// Implement the MBean
@Component
@ManagedResource(objectName = "com.example:type=Configuration")
public class Configuration implements ConfigurationMBean {
    private String applicationName = "MyApp";

    @Override
    public String getApplicationName() {
        return applicationName;
    }

    @Override
    public void updateApplicationName(String name) {
        this.applicationName = name;
    }
}


在这个示例中,Configuration类使用@ManagedResource进行了注释,使其作为MBean可用,并且通过JMX客户端可以访问操作和属性。

在Spring Boot中暴露MBeans是一个强大的功能,它增强了应用程序的管理和监控能力。通过按照上述步骤,开发人员可以为外部工具提供对应用程序内部的动态访问,提供对运行时行为的窗口,并允许实时调整。这不仅有助于调试和性能调优,还符合构建可管理、健壮应用程序的最佳实践。

视频

最后的话

尤其是JMX及其与Spring等框架的集成所提供的高级管理工具,为开发人员提供了应用程序监视、配置和调试的强大能力。通过理解和利用这些工具,开发人员可以实现对其应用程序的更深层次控制,提升性能和可靠性。无论是通过图形界面还是类似JMXTerm这样的命令行实用程序,对运行时环境中应用程序的动态操作和监控都为有效的软件开发和管理开辟了新途径。随着开发与运营之间的桥梁不断缩小,掌握这些高级工具对于任何希望在当今快节奏的技术景观中脱颖而出的开发人员来说都变得至关重要。

推荐阅读: 程序员在北京有哪些可以选择的互联网中厂(附薪资)

本文链接: 使用JMX进行调试再探讨