`
MauerSu
  • 浏览: 513574 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

转:Java 理论与实践: 用 JMX 检测应用程序

    博客分类:
  • J2EE
 
阅读更多
源:http://www.ibm.com/developerworks/cn/java/j-jtp09196/#ibm-pcon
评:
只需添加 bean 就可实现立即可视
调试器和分析器可以提供对应用程序的行为的深入观察,但在出现严重问题之前,这些工具通常用不上。将监视挂钩(hook)构建到应用程序内,会使理解程序的执行变得更容易而且不会破坏调试器。既然 Java 管理扩展(JMX)已经构建进了 Java™ SE 平台,而且 jconsole 查看器提供了统一的监视 GUI,那么用 JMX 为应用程序提供一个窗口,要比以前更加容易而且更为有效。


有多少次您曾经注视着运行中的应用程序,问自己:“它到底在做什么?为什么用了这么长时间呢?” 在这些时刻,您可能会想如果自己在应用程序中构建了更多的监视功能就好了。例如,在服务器应用程序中,能够查看排队等候处理的任务的数量和类型、当前正在处理的任务、过去一分钟或一小时内的吞吐量统计、平均任务处理时间等。这些统计值容易搜集,但是在需要数据的时候,如果没有非侵入性的数据检索机制,那么这些值就不太有用。
可以用许多方式导出操作性数据——可以把周期性统计快照写入日志文件、创建 Swing GUI、使用内嵌的 HTTP 服务器在 Web 页面上显示统计值或者发布可以用来查询应用程序的 Web 服务。但是在缺少监视和数据发布基础设施的情况下,多数应用程序开发人员都做不到这些,因此造成对应用程序工作情况的了解要比预期的少很多。
JMX
在 Java 5.0 中,类库和和 JVM 提供了一种全面的管理和监视基础设施——JMX。JMX 是一种用来提供可以远程访问的管理接口的标准措施,也是一种向应用程序添加灵活且强大的管理接口的简易方式。被称作受管 bean(MBean)的 JMX 组件,是提供与实体的管理有关的访问器和业务方法的 JavaBean。每个受管的实体(可能是整个应用程序或应用程序中的服务)实例化一个 MBean 并用可读懂的名称注册它。支持 JMX 的应用程序依赖于 MBeanServer,它充当 MBean 的容器,提供远程访问、命名空间管理和安全服务。在客户端,jconsole 工具可以充当统一的 JMX 客户机。结合两者,对 JMX 的平台支持极大地降低了使应用程序支持外部管理接口所需的工作和努力。
除了提供 MBeanServer 实现,Java SE 5.0 还提供 JVM 以更方便地了解内存管理、类装入、活动线程、日志和平台配置的状态。多数平台服务的监视和管理在默认情况下都是开启的(性能影响最小),所以只需要连接应用程序与 JMX 客户机即可。图 1 给出了 jconsole JMX 客户机(JDK 的一部分) ,它显示了其中一个内存管理视图——一段时间内的堆使用情况。Perform GC 按钮则证明了 JMX 可以提供 除了查看操作统计值之外的初始化操作的功能。
图 1. 用 jconsole 查看堆使用情况
用 jconsole 查看堆使用情况
传输和安全性
JMX 指定了在 MBeanServer 和 JMX 客户之间通信所使用的协议,协议可以在各种传输机制上运行。可以使用针对本地连接的内置传输,及通过 RMI、socket 或 SSL 的远程传输(可以通过 JMX Connector API 创建新的传输)。认证是由传输执行的;本地传输允许用相同的用户 ID 连接到运行在本地系统上的 JVM;远程传输可以用口令或证书进行认证。本地传输在 Java 6 下默认就是启用的。要在 Java 5.0 下启用它,需要在 JVM 启动时定义系统属性 com.sun.management.jmxremote。“Monitoring and Management using JMX” 这份文档(请参阅参考资料)描述了启用和配置传输的配置步骤。
回页首
检测 Web 服务器
检测应用程序来使用 JMX 很容易。像其他许多远程调用框架(RMI、EJB 和 JAX-RPC)一样,JMX 也是基于接口的。要创建管理服务,需要创建指定管理方法的 MBean 接口。然后可以创建一个 MBean 来实现此接口、实例化它及把它注册到 MBeanServer。
清单 1 显示了网络服务(例如 Web 服务器)的 MBean 接口。它提供了检索配置信息(例如端口号)和操作性信息(例如服务是否启动)的 getter。它还包含查看和修改可配置参数(例如当前日志级别)的 getter 和 setter,还有调用管理操作(例如 start() 和 stop())的方法。
清单 1. 某个 Web 服务器的 MBean 接口
public interface WebServerMBean {
    public int getPort();

    public String getLogLevel();
    public void setLogLevel(String level);

    public boolean isStarted();
    public void stop();
    public void start();
}
实现 MBean 类通常非常直接明了,因为 MBean 接口要反映现有实体或服务的属性和管理操作。例如,MBean 中的 getLogLevel() 和 setLogLevel() 方法会直接转给被 Web 服务器使用的 Logger 上的 getLevel() 和 setLevel() 方法。JMX 做了一些命名限制。例如,MBean 接口名称必须以 MBean 结尾,FooMBean 接口的 MBean 类必须叫作 Foo。(可以用更高级的 JMX 特性——动态 MBean 来去除这个限制。)把 MBean 注册到默认的 MBeanServer 也很容易,如清单 2 所示:
清单 2. 用内置的 JMX 实现注册 MBean
  public class WebServer implements WebServerMBean { ... }

  ...

  WebServer ws = new WebServer(...);
  MBeanServer server = ManagementFactory.getPlatformMBeanServer();
  server.registerMBean(ws, new ObjectName("myapp:type=webserver,name=Port 8080"));
传递给 registerMBean() 的 ObjectName 标识了受管实体。因为预见到指定应用程序可能包含许多受管实体,所以名称包含域(清单 2 中的 “myapp”)和许多标识域中的受管资源的键-值对。“name” 和 “type” 这两个键是常用的,在使用的时候,name 应当在域中所有的同类 MBean 中能够唯一地标识受管实体。也可以指定其他键-值对,而且 JMX API 还包含进行对象名称通配匹配的工具。
创建并注册了 MBean 之后,立即就可以把 jconsole 指向应用程序(在命令行输入 jconsole)并在 “MBeans” 视图中查看它的管理属性和操作。图 2 显示了 jconsole 中针对新 MBean 的 Attributes 标签,图 3 显示了 Operations 标签。使用反射,JMX 可以指出哪个属性是只读的(Started、Port),哪个属性是可读写的(LogLevel),而且 jconsole 允许修改读写属性。如果读写属性的 setter 抛出异常(例如 IllegalArgumentException),JMX 就把异常报告给客户机。
图 2. jconsole 中 MBean 的 Attributes 标签
jconsole 中 MBean 的 Attributes 标签
图 3. jconsole 中 MBean 的 Operations 标签
jconsole 中 MBean 的 Operations 标签
数据类型
MBean 中的访问器和操作能够用任何其签名形式的原语类型,以及 String、Date 和其他标准库类。也可以使用这些允许的类型的数组和集合。MBean 方法也可以使用其他可以序列化的数据类型,但是这样做会造成互操作性问题,因为类文件也必须对 JMX 客户机可用。(如果使用 RMI 传输,可以使用 RMI 的自动类下载特性完成这项任务。)如果想在管理接口中使用结构化数据类型,还想避免与类可用性相关的互操作性问题,可以使用 JMX 的开放 MBean 特性来表达复合或表格数据。
回页首
检测服务器应用程序
在创建管理接口时,某些参数和操作的特点很自然地就表明这些参数和数据应当被包含在内,例如配置参数、操作统计值、调试操作(例如修改日志级别或把应用程序状态导出到文件)、生命周期操作(启动、停止)。检测一个应用程序,让它支持对这些属性和操作的访问,通常相当容易。但是,要从 JMX 获得最大价值,就要在设计时考虑什么数据在运行时对用户和操作员有用。
如果用 JMX 了解服务器应用程序的工作情况,需要一种标识和跟踪工作单元的机制。如果使用标准的 Runnable 和 Callable 接口描述任务,通过让任务类自描述(例如实现toString() 方法),可以在任务生命周期内跟踪它们,并提供 MBean 方法来返回等候中、处理中和完成的任务列表。
清单 3 中的 TrackingThreadPool 演示的是 ThreadPoolExecutor 的一个子类,它及时给出正在处理中的是哪些任务,以及已经完成的任务的时间统计值。它通过覆盖 beforeExecute() 和 afterExecute() 挂钩,并提供能检索所搜集数据的 getter,实现这些任务。
清单 3. 搜集处理中的任务和平均的任务时间统计值的线程池类
public class TrackingThreadPool extends ThreadPoolExecutor {
    private final Map<Runnable, Boolean> inProgress
        = new ConcurrentHashMap<Runnable,Boolean>();
    private final ThreadLocal<Long> startTime = new ThreadLocal<Long>();
    private long totalTime;
    private int totalTasks;

    public TrackingThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime,
       TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        inProgress.put(r, Boolean.TRUE);
        startTime.set(new Long(System.currentTimeMillis()));
    }

    protected void afterExecute(Runnable r, Throwable t) {
        long time = System.currentTimeMillis() - startTime.get().longValue();
        synchronized (this) {
            totalTime += time;
            ++totalTasks;
        }
        inProgress.remove(r);
        super.afterExecute(r, t);
    }

    public Set<Runnable> getInProgressTasks() {
        return Collections.unmodifiableSet(inProgress.keySet());
    }

    public synchronized int getTotalTasks() {
        return totalTasks;
    }

    public synchronized double getAverageTaskTime() {
        return (totalTasks == 0) ? 0 : totalTime / totalTasks;
    }
}
清单 4 中的 ThreadPoolStatusMBean 显示了 TrackingThreadPool 的 MBean 接口,它提供了活动任务、活动线程、完成任务、等候任务的计数,还提供了当前等候执行和正在执行的任务的列表。在管理接口中包含等候和执行任务的列表,让您既可以看到应用程序的工作难度,又可以看到它目前的工作内容。这个特性不仅让您可以洞察应用程序的行为,还能洞察它正在操作的数据集的性质。
清单 4. TrackingThreadPool 的 MBean 接口
public interface ThreadPoolStatusMBean {
    public int getActiveThreads();
    public int getActiveTasks();
    public int getTotalTasks();
    public int getQueuedTasks();
    public double getAverageTaskTime();
    public String[] getActiveTaskNames();
    public String[] getQueuedTaskNames();
}
如果任务的重量级足够,那么甚至可以再进一步,在每个任务提交时都为它注册一个 MBean (然后在任务完成时再取消注册)。然后可以用管理接口查询每个任务的当前状态、运行了多长时间,或者请求取消任务。
清单 5 中的 ThreadPoolStatus 实现了 ThreadPoolStatusMBean 接口,它提供了每个访问器的明显实现。与 MBean 实现类中的典型情况一样,每个操作实现起来都很细碎,所以把实现委托给了底层受管对象。在这个示例中,JMX 代码完全独立于受管实体的代码。TrackingThreadPool 对于 JMX 一无所知;通过为相关的属性提供管理方法和访问器,它提供了自己的编程管理接口。 还可以选择在实现类中直接实现管理功能(让 TrackingThreadPool 实现 TrackingThreadPoolMBean 接口),或者单独实现(如清单 4 和 5 所示)。
清单 5. TrackingThreadpool 的 MBean 实现
public class ThreadPoolStatus implements ThreadPoolStatusMBean {
    private final TrackingThreadPool pool;

    public ThreadPoolStatus(TrackingThreadPool pool) {
        this.pool = pool;
    }

    public int getActiveThreads() {
        return pool.getPoolSize();
    }

    public int getActiveTasks() {
        return pool.getActiveCount();
    }

    public int getTotalTasks() {
        return pool.getTotalTasks();
    }

    public int getQueuedTasks() {
        return pool.getQueue().size();
    }

    public double getAverageTaskTime() {
        return pool.getAverageTaskTime();
    }

    public String[] getActiveTaskNames() {
        return toStringArray(pool.getInProgressTasks());
    }

    public String[] getQueuedTaskNames() {
        return toStringArray(pool.getQueue());
    }

    private String[] toStringArray(Collection<Runnable> collection) {
        ArrayList<String> list = new ArrayList<String>();
        for (Runnable r : collection)
            list.add(r.toString());
        return list.toArray(new String[0]);
    }
}
为了演示这些类如何提供对应用程序操作的内容的了解,请考虑这样一个 Web 搜寻应用程序,它把工作分成两类任务:获取远程页面,对页面进行索引。每个任务分别用清单 6 所示的 FetchTask 或 IndexTask 描述。可以创建 ThreadPoolStatus MBean,提供处理这些任务所使用的线程池的管理接口,并把它用 JMX 注册。
清单 6. Web 搜寻应用程序中使用的 FetchTask 类
public class FetchTask implements Runnable {
    private final String name;

    public FetchTask(String name) {
        this.name = name;
    }

    public String toString() {
        return "FetchTask: " + name;
    }

    public void run() {  /* Fetch remote resource */  }
}
当此程序处理每个页面时,可能还会对新任务进行排队以获取这个页面上链接的页面,所以在指定时间内,可能会既有获取任务又有尚未完成的索引任务。能够正确地判断正在处理哪个页面,或者正在等候处理哪个页面,不仅让您可以理解应用程序的性能特征,还可以理解应用程序所操作的数据的特征。
图 4 显示了正在处理 whitehouse.gov 站点的 Web 搜寻程序的快照。从图中可以看到已经获取并索引了主页,程序现在的工作是获取和索引直接从该主页链接出的页面。单击 Refresh 按钮,可以对应用程序的工作流程进行取样,它可以提供许多关于应用程序工作情况的信息,却不需引入大量日志或者在调试器中运行应用程序。
图 4. Web 搜寻应用程序中的活动任务和排队任务
Web 搜寻应用程序中的活动任务和排队任务
回页首
结束语
结合平台内的 JMX 支持和 jconsole JMX 客户机可以提供一种向应用程序添加管理和监视功能的轻松方式。即使是没有具体管理需求的应用程序,为它们构建这些功能也会让您对程序的运行及其所处理的数据的性质获得深入了解,而且不需太多的工作和努力。如果应用程序导出管理接口,此接口让您可以查看它操作的内容,那么您就会更加了解它的运行状态——对它是否按预期的方式工作也会更有信心——而不必求助于额外的工具(例如添加日志代码或使用调试器或分析器)。
分享到:
评论

相关推荐

    Java理论与实践:用JMX检测应用程序

    Java理论与实践:用JMX检测应用程序是一种利用Java管理扩展(JMX)技术来增强应用程序监控和管理能力的方法。JMX是一种标准的框架,它允许开发者创建和注册受管bean(MBean),这些MBean提供了对应用程序内部状态的...

    Java系列深入解析Java多线程

    Java多线程的掌握需要理论与实践相结合,通过设计并发程序,分析运行效果,逐步提高对多线程的理解和运用能力。在实际开发中,合理使用多线程技术能够显著提高程序性能,但同时也需要注意潜在的并发问题,确保程序的...

    APress-Taming-Java-Threads-Code.rar_taming java threads_threads

    7. **性能调优**:书中将介绍如何通过监控和调整线程参数来提升并发性能,包括Java的JMX、VisualVM等工具的使用。 8. **实战案例**:通过一系列的实际案例,如Web服务器、数据库连接池等,展示如何在实际项目中应用...

    检测JSP服务器内存的Ajax程序_systemjc.rar

    【标题】"检测JSP服务器内存的Ajax程序_systemjc.rar"是一个与计算机毕业设计相关的资源,其中涵盖了使用JSP、Java语言以及Ajax技术来监测服务器内存的实践操作。这个项目旨在帮助学生或开发者理解如何在实际环境中...

    我的全部java项目(博客项目的代码)

    这些文件名揭示了博主在Java编程方面的一些学习和实践经历,涵盖了从基础到相对复杂的项目。下面我们将逐一解析这些知识点: 1. **Lesson2016-4-5MyServer** 和 **Lesson2016-4-5MyClient**: 这两个文件名可能...

    阿里巴巴Java性能调优实战(2021华山版).rar

    《阿里巴巴Java性能调优实战(2021华山版)》是一本专注于Java应用程序性能优化的专业书籍,由阿里巴巴的技术专家团队倾力打造。这本书基于阿里巴巴的实际业务场景,结合丰富的实践经验,为Java开发者提供了深入、...

    java性能权威指南高清

    《Java性能权威指南》是一本深受Java开发者喜爱的进阶读物,专注于讲解如何优化Java应用程序的性能。这本书详尽地探讨了Java性能调优的各个方面,为读者提供了丰富的实践经验和理论知识,帮助开发者深入理解Java平台...

    JVM虚拟机入门到实战资料

    Java虚拟机(JVM)是Java程序运行的核心组件,它为Java应用程序提供了跨平台的运行环境。本套资料从入门到实战,全面涵盖了JVM的基础知识、高级特性、实战应用以及面试常见问题,旨在帮助开发者深入理解JVM的工作...

    [其他类别]检测JSP服务器内存的Ajax程序_systemjc毕业设计—(包含完整源码,可运行).rar

    该资源是一个毕业设计项目,主要涉及的技术包括Ajax...总的来说,这个项目结合了前端与后端技术,通过Ajax实现了前后端的通信,对JSP服务器的内存使用情况进行实时监控,为理解和实践Web应用的性能优化提供了实例参考。

    szjvm-master.zip

    《实战Java虚拟机》这本书是Java开发者深入理解JVM(Java Virtual Machine)的重要参考资料,它提供了丰富的实践案例和源码,帮助读者从实际操作中掌握JVM的工作原理和调优技巧。"szjvm-master.zip"这个压缩包包含了...

    spring-reference.pdf

    8. **示例应用更新**:更新了示例应用程序,展示了如何使用新特性。 9. **文档改进**:文档得到了全面更新,提供了更详尽的说明和指导。 四、核心技术和实践 《Spring框架2.5版参考手册》深入探讨了Spring框架的...

    JVM Diagnostics Guide 1.4.2

    这份指南深入解析了如何诊断和解决与JVM性能、内存管理、线程状态等相关问题,帮助开发者优化应用程序的运行效率和稳定性。以下是该指南可能涵盖的一些关键知识点: 1. **JVM概述**:介绍Java虚拟机的原理和作用,...

    WebLogic Server 10.3集群管理中文培训ppt+练习材料

    - 自动故障恢复,包括应用程序和服务的迁移。 7. **安全与网络配置**: - 集群内的安全设置,如SSL(Secure Sockets Layer)和TLS(Transport Layer Security)。 - 网络配置,如多网络接口、IP地址和端口规划。...

    EJB3.0学习之运行环境配置

    JDK5.0,即Java Development Kit版本5.0,是运行EJB3.0应用程序的基本前提。确保系统中安装了正确版本的JDK,这是因为在EJB3.0规范中利用了Java5.0的特性,如泛型、枚举、可变参数和增强的for循环等。安装JDK时,需...

    Java垃圾回收调优实战

    Java垃圾回收调优是优化Java应用程序性能的关键环节,特别是对于那些需要处理大量数据或执行高并发操作的应用。垃圾回收(Garbage Collection, GC)的主要任务是自动管理内存,释放不再使用的对象,避免内存泄漏,...

    一种无线网络管理系统方案设计.docx

    JMX是一种为管理应用程序和服务提供框架的Java技术,它允许开发者创建可管理和监控的组件,并且可以与其他管理系统集成,实现跨平台的管理功能。 系统设计主要包括以下几个核心模块: 1. **体系结构设计**:系统...

    面试

    Java作为广泛应用的编程语言,其面试通常会涵盖语法基础、面向对象设计、数据结构与算法、多线程、JVM内存模型、Spring框架以及数据库等相关知识。下面我们将详细探讨这些关键点。 1. **Java语法基础**:面试时,...

    get-jvm:研究JVM并测试其机制

    通过"get-jvm"项目,我们可以将理论知识与实践相结合,加深对JVM运行机制的理解,这对于提升我们的Java开发技能至关重要。此外,该项目也可以作为教学和研究的案例,帮助更多的人掌握JVM的相关知识。 总之,"get-...

Global site tag (gtag.js) - Google Analytics