Java 系统运行时性能和可用性监控

发表于:2008-8-28 09:36

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Nicholas Whitehead    来源:IBM

  通过 JMX 监控应用程序资源

  目前为止,我已经讨论了通过 JMX 监控惟一标准的 JVM 资源。但是,许多应用程序架构,如 Java EE,可以通过 JMX 公开重要的特定于应用程序的指标(这取决于供应商)。一个典型的例子是 DataSource 利用率。DataSource 是一个用于将连接池化到外部资源(通常为数据库)的服务,这限制了并发连接的数量,以保护资源不受恶意应用程序的占用。监控数据源是整个监控计划中的关键环节。由于 JMX 抽象层,该流程与之前介绍的类似。

  下面是来自 JBoss 4.2 应用服务器实例的典型数据源指标:

  • 可用连接数:当前池中可用连接的数量。
  • 连接数:连接池与数据库建立的实际物理连接的数量。
  • 最大使用连接数:池中正在使用的连接的上限标记。
  • 正在使用的连接数:当前正在使用的连接数量。
  • 已创建的连接数:为该池创建的连接总数。
  • 已部署的连接数:为该池部署的连接总数。

  现在,收集器将使用批属性检索,并在一个调用中获取所有属性。惟一需要注意的是,您需要查询返回的数据,以接通不同的数据和跟踪程序类型。DataSource 指标在没有活动时也是不会变化的,因此,要使数值变化,您需要生成一些负载。清单 4 显示 DataSource 收集器的 collect() 方法:

清单 4. DataSource 收集器

public void collect() {

   try {

      log("Starting DataSource Collection");

      long start = System.currentTimeMillis();

      ObjectName on = objectNameCache.get("DS_OBJ_NAME");

      AttributeList attributes  = jmxServer.getAttributes(on, new String[]{

"AvailableConnectionCount",

            "MaxConnectionsInUseCount",

            "InUseConnectionCount",

            "ConnectionCount",

            "ConnectionCreatedCount",

            "ConnectionDestroyedCount"

      });

      for(Attribute attribute: (List<Attribute>)attributes) {

         if(attribute.getName().equals("ConnectionCreatedCount")

            || attribute.getName().equals("ConnectionDestroyedCount")) {

               tracer.traceDeltaSticky((Integer)attribute.getValue(), hostName,

               "DataSource", on.getKeyProperty("name"), attribute.getName());

         } else {

            if(attribute.getValue() instanceof Long) {

               tracer.traceSticky((Long)attribute.getValue(), hostName, "DataSource",

                  on.getKeyProperty("name"), attribute.getName());

            } else {

               tracer.traceSticky((Integer)attribute.getValue(), hostName,

                  "DataSource",on.getKeyProperty("name"), attribute.getName());

            }

         }

      }

      // Done

      long elapsed = System.currentTimeMillis()-start;

      tracer.trace(elapsed, hostName, "DataSource", "DataSource Collector",

         "Collection", "Last Elapsed Time");

      tracer.trace(new Date(), hostName, "DataSource", "DataSource Collector",

         "Collection", "Last Collection");        

      log("Completed DataSource Collection in ", elapsed, " ms.");        

   } catch (Exception e) {

      log("Failed:" + e);

      tracer.traceIncident(hostName, "DataSource", "DataSource Collector",

         "Collection", "Collection Errors");

   }     

}

  图 8 显示了 DataSource 收集器的相应指标树:

图 8. DataSource 收集器指标树:

  监控 JVM 中的组件

  本节介绍的技巧可用于监控应用程序组件、服务、类和方法。相关的主要区域如下:

  • 调用速率:调用服务或方法的速率。
  • 调用响应速率:服务或方法响应的速率。
  • 调用错误率:服务或方法生成错误的比率。
  • 调用运行时间:调用在每个间隔时间内的平均、最短和最长运行时间。
  • 调用并发性:并发调用服务或方法时执行的线程数。

  使用 Java SE 5(和更新版本)ThreadMXBean 的一些实现提供的指标,还可以收集以下指标:

  • 系统和用户 CPU 时间:调用某方法占用的 CPU 时间。
  • 等待数量和总等待时间:调用某方法或服务时,等待线程的实例数量和总占用时间。当线程进入 WAITING 或 TIMED_WAITING 等待状态并暂停另一个线程的活动时将发生等待事件。
  • 阻塞数量和总阻塞时间:在调用某个方法或服务时,处于 BLOCKED 状态的线程的实例数量和总占用时间。当线程等待监控锁进入或重新进入同步阻塞时会发生阻塞事件。

  还可以使用备选工具集和本机接口来确定这些指标和其他指标,但这通常涉及某种级别的开销,从而造成不必要的生产运行时监控。已经说过,指标本身,甚至在收集时,是低级的。它们的作用也许仅限于分析趋势,并且很难与无法通过其他手段确定的因果效应相关联。

  所有上述指标都可以通过插装类和方法的流程来收集,以便于收集和跟踪目标 APM 系统的性能数据。可以采用各种技巧来直接插装 Java 类,或者通过它们来间接计算性能指标:

  • 源代码插装:最基本的技巧是在源代码阶段添加插装,这样编译和部署后的类就已经在运行时包含了插装。在某些情况下,这种方法具有意义,并且一些特定的实践使它成为可行的流程和投资。
  • 截取:通过截取程序(执行测定和跟踪)转移调用,可以实现有效和准确的跟踪,而无需接触目标类、它们的源代码和运行时字节码。这种实践简单可取,因为存在许多 Java EE 框架和其他流行的 Java 框架:
    • 通过配置支持抽象。
    • 支持类注入和通过接口引用。
    • 有某些情况下直接支持截取栈概念。执行流程经过定义了配置的对象栈,其作用是接收调用并执行一些处理,然后继续传递。
  • 字节码插装:该流程将字节码注入到应用程序类中。注入的字节码将添加性能数据收集插装,该插装被作为新类的一部分调用。这个流程有时极为有效,因为插装是完全经过编译的字节码,并且代码的执行路径以最细化的方式扩展,同时仍然能够收集数据。它的另一个优点是无需修改初始源代码,并且其对环境的配置更改也可能最少。此外,通用模式和字节码注入技巧允许对源代码不可用的类和库进行插装,许多第三方类属于这种情况。
  • 类包装:该流程使用另一个类来包装或替换目标类,前者实现了相同功能,同时也包含了插装。

  在本文的第 1 部分中,我只讨论基于源代码的插装;您将在第 2 部分中了解更多关于截取、字节码插装和类包装的信息。(从拓扑学的角度来说,截取、字节码插装和类包装的本质完全相同,但它们实现结果的操作有稍微不同的含义)。

  异步插装

异步插装是类插装中的基本问题。上一节讨论了轮询性能数据的概念。如果轮询完成得足够好,则它应该不会对核心应用程序性能或开销造成影响。相反,插装应用程序代码本身会直接修改和影响核心代码的执行。任何插装的目标都必须是无论如何,不产生危害。开销损失必须尽可能接近忽略不计。事实上,消除测量本身中的极细微的损失是不可能的,但是,在获取性能数据之后,保持其余跟踪进程异步是非常重要的。可以采用若干种模式来实现异步跟踪。图 9 演示了异步跟踪的实现方法概览:

  图 9. 异步跟踪

  图 9 演示了一个简单的插装截取程序,它通过捕获调用的起始时间来测量它的运行时间,然后将测量数据(运行时间和指标复合名称)分发给处理队列。然后,线程池读取该队列,获取测量数据并完成跟踪流程。

65/6<123456>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号