Oracle 融合中间件附带了一个极好的工具集,用于对可疑应用程序行为进行分析。

2010 年 1 月发布

自 1995 年 Java 诞生以来,用 Java 编写的应用程序变得越来越复杂。随着时间的推移,人们开发出了许多模型和架构来应对日益复杂的需求。遗憾的是,解决方案不会变得更加轻便容易,而是更为复杂费力。每增加一个新组件都会增加延迟,从而使解决方案速度更慢。

当速度慢下来时,通常人们总是怀疑所使用的技术。人们怀疑的对象各不相同,可能怀疑数据库也可能怀疑中间件,这取决于他们的技术背景。人们通常怀疑得最少的是网络或浏览器。当然,不加证明就怀疑所使用的技术是不公平的,而且网络或浏览器可极大地影响速度。

为了找出耗费时间的真正原因,人们需要在特定的使用情况配置文件环境下对应用程序进行分析并提供无懈可击的证据。令人庆幸的是,Oracle 融合中间件包含了各种工具以协助您完成上述工作。

常见可能原因

性能低下可能有许多原因。下面是一些可能造成应用程序性能低下的最为常见的问题:

内存泄漏。内存泄漏 这个术语有点误导。尽管您的计算机或 JVM 中的内存不会象水一样“泄漏”,但随着时间的流逝,您会注意到可用内存会比预期的少。既然 JVM 垃圾回收器 (GC) 通过从内存中删除不使用的对象来收回不使用的内存,为何还会出现这种情况?这很可能是因为,有些可从内存中删除的对象因其没有表现为未使用而不能被 GC 所发现。

大多数的内存泄漏是由于被遗漏的引用或实现不良的自生缓存而引起。(提示:如果您不使用软引用或弱引用,就不能利用 GC 来自动缩减缓存。)这些泄漏会增加 GC 的调用次数及其发现要释放的少量内存所需的时间。这样导致的应用程序开销会影响用户的体验。找出并消除这些内存泄漏的情况是性能调优的主要目标。

数据建模不良。数据建模对应用程序的运行时行为有极大的影响。我们应该知道,在现代的多层应用程序中,数据能够并且会跨越进程边界。跨越这些边界需要花费时间,因为须将二进制形式的数据转换为一种传输格式。然而,随着这种序列化和反序列化过程的实现,比起数据待在进程内的情况,程序速度变得更慢了。所使用的数据类型以及实现该过程的方式对整体性能有着极大的影响。

例如,日期或时间戳通常保存为 64 位的值(Java 的 Long 类型)。然而,选择用 Calendar 类型来保存此类信息也没有问题。Calendar 类型一般会占用 80 个字节。因此,通过选用合适的类型来保存时间戳信息,可以轻松节省 72 个字节。

另外,相比于非序列化,选择外化可极大地提高性能。缺点是外化会为开发期间高度紧迫的编程实践带来额外的成本开销。

网络输入/输出流量较高有关网络计算的一个谬论是,“快速的”网络。一旦您需要进行远程调用,那么绝对会更为费时。减少网络调用的次数或大小都可节省应用程序所需时间以供他用。

节省网络时间相当容易。其中一个方法是,让远程应用程序完成自己的工作。一般来说,非常具体的调用只返回一个正确结果,与那些返回数千个不需要的结果的调用相比,显然更为快速。

JVM 配置不良。每个 JVM 都可通过许多命令行开关来配置,其中许多开关会直接或间接地影响应用程序的运行时行为。例如,几乎每个 JVM 用户都知道用于定义 JVM 内存大小(或称为“堆”)的开关。而其他开关不太为人所熟知,但恰当地设置这些开关,可以在特定的使用情况配置文件环境下提高性能;然而,在另一个不同的使用情况配置文件环境下,同样的设置也可能会降低性能。

数据库速度慢。在一个多层架构中,数据库速度慢是一个不当托词。相反,在应用程序架构的庞大组织中,数据库几乎总是速度最快的那部分。另一方面,缺失索引可极大地降低性能。数据库经过充分调优,SQL 语句使用恰当,这两者一起有助于实现最佳的架构。

现在我们已了解了导致性能降低的一般可能原因,接下来我们要做什么?为了能够提供证据来说明性能降低是由其中某个原因导致的,在合适的时间使用合适的工具是很重要。但在我们了解这些工具之前,先了解一下可用于 Oracle 融合中间件的运行时环境。

Oracle 融合中间件中的 Java 虚拟机

安装 Oracle WebLogic Server 作为大多数配置的基础时,您可以决定要使用哪种 JVM。截至撰写本文时,随取随用的 WebLogic Server 提供 Sun JVM 1.6 或 Oracle JRockit JVM 1.6。每种 JVM 都有自己的特质,适用于特定的应用程序配置文件。哪种 JVM 最适合您的应用程序取决于应用程序配置文件以及 JVM 处理该配置文件的方式。要找出最适合您的应用程序配置文件的 JVM,进行全面的测试和调优是非常重要的。

Sun JVM

Sun JVM 是 Java 参考实现,应该用它来验证应用程序是否按照预期运行。

Sun JVM 的内存模型包含两个主要的内存区域:年轻代年老代。年轻代区域又分为一个 Eden 空间 和两个存活空间。另外,还有一个可用的持久代 (PermGenSpace)。

动态创建的对象开始时存放于 Eden Space 中。在垃圾回收期间,这些对象移至存活空间然后再移至年老代,直到它们因未被使用而被 GC 回收。PermGenSpace 存储静态数据,如类、常量值和静态变量。

如果 PermGenSpace 很小,其中却加载了过多的类、静态变量和常量值,Sun JVM 可能很快就会用光内存。由于 PermGenSpace 是从整体堆容量中获取其空间的,其空间一定相当小。当年老代持续占用可用空间的 70-80% 时,我们就可以认为发生了内存泄漏。而当占用了 90% 时,情况就非常严重了,应立即进行分析。

高度饱和的内存使用会影响运行时,因为此时对 GC 的调用会更为频繁并且 GC 需要更长的周期时间才能找到可回收的区域。这些区域通常过小,GC 需要更多的周期来完成内存请求。当情况变得越来越糟时,JVM 只能执行 GC,因而应用程序挂起。

Sun JVM 附带有各种 GC。每种 GC 对于特定的使用情况配置文件来说都是完美的。有关可用 GC 的详细信息,可参阅 JVM 文档。可通过命令行开关来调优 GC 及其行为。

Oracle JRockit JVM

Oracle JRockit JVM 是一个 Java 兼容实现,其设计旨在实现针对 Intel 硬件的非常快速的 JVM。JRockit 的内存模型类似于 Sun JVM 的内存模型,它也有年轻代和年老代区域。新对象和存活时间尚短的对象存放于年轻代区域中,而存活时间较长的对象可存放于年老代区域中。Oracle JRockit 内存模型没有 PermGenSpace,因此不会因 PermGenSpace 饱和而引发任何内存不足之异常情况。

Oracle JRockit JVM 同样提供各种 GC。特别是为了获得更佳的运行时行为,值得尝试并发标记扫描 GC 和并行标记扫描 GC。就 Sun JVM 而言,这些 GC 可通过命令行开关来明确地设置,并且它们是应用程序使用情况配置文件的优化配置中的一部分设置。

现在,您对 Oracle 融合中间件 JVM 有了些基本了解,下面我们将概要介绍用于诊断性能问题的基本工具集。根据您所采用的 JVM,可以使用不同的工具组合。

Oracle Enterprise Manager

为了发现性能问题,您应该始终从 Oracle Enterprise Manager Fusion Middleware Control 控制台开始。此管理软件可随大多数组件安装,因此可能已经可以使用了。它会显示应用程序的运行时状况的有关重要信息。

该管理控制台的 Summary 屏幕显示实例的当前状态汇总。除了 Response and Load 图形外,您还应仔细看看 Summary portlet。这个 portlet 在非常小的屏幕区域上显示可行信息。所显示的信息对于任何 Java EE 应用程序都非常重要,因为其中包括 Servlet/JSP、JMS、EJB 以及 JDBC 和 JTA 使用情况指示器。


Oracle 融合中间件中的性能调优工具概述
图 1 Summary 屏幕


如果您的应用程序使用了大量的 Servlet 和 JSP,则下面的 Most Requested portlet 值得一看。如果响应时间长得离谱,则表示性能不佳。


Oracle 融合中间件中的性能调优工具概述
图 2
Most Requested portlet


而且,永远不要低估日志文件的作用!日志文件是您寻找各种问题指示的第一场所。时间和空间方面的其他引用结合使用,您可以轻松获得对应用程序的运行时行为的更好了解。下面的屏幕截图显示 Log Messages 搜索窗口。

Oracle 融合中间件中的性能调优工具概述
图 3
Log Messages 搜索窗口


使用 VisualVM

VisualVMJVisualVM 工具主要面向 Sun JVM。自 JDK 1.6.0_10 以来,JVisualVM 成为 JDK 的一部分,而 VisualVM 则可作为独立的应用程序单独安装。这两个工具有相同的基础并且都可通过插件进行扩展,VisualVM 可更好地支持更多的插件。VisualVM 可用于 JDK 版本 1.5.0 以及更高版本,但在用于版本 1.6.0 时确实表现更佳。

每个分析均从 VisualVM 控制台开始。这会以非常整洁的方式显示所有运行时参数(无需挖掘某些启动脚本)。只需单击 Monitor 选项卡即可显示 JVM 的当前状态。Threads、Profiler、Memory Sampler 或 Visual GC 选项卡中显示更多详细信息。


Oracle 融合中间件中的性能调优工具概述
图 4 VisualVM 控制台窗口


Threads 选项卡显示 JVM 中当前正在使用的所有线程。只需单击 Thread Dump 按钮即可创建线程信息的一个转储文件,稍后可通过 Thread Dump Analyzer 插件对文件进行分析。


Oracle 融合中间件中的性能调优工具概述
图 5 VisualVM 中的 VisualGC


VisualGC。当需要找出与 Sun JVM 内存模型有关的问题时,可选择使用 VisualGC 插件。在 jvmstat 3.0 for JDK 1.5.0 附带的 VisualGC 工具的基础上,此插件以其 Class Loader Time、Compile Time(针对 JIT)和 GC Time 显示 JVM 的所有联机状态。如果应用程序不久之后变得越来越慢,您应考虑使用 VisualGC 对 JVM 内存进行分析!


Oracle 融合中间件中的性能调优工具概述
图 6 VisualVM 的 Threads 选项卡显示所有线程的状态。


内存抽样和堆转储。要分析对象使用可用内存的情况,可以使用两个工具。Memory Sampler 为您提供一个联机内存视图,而 Heap Dump Analyzer 可用于提供脱机内存视图。只需按下一个按钮即可随时创建堆信息转储文件。VisualVM 会自动读取该转储文件并显示其结果(如下所示)。


Oracle 融合中间件中的性能调优工具概述
图 7 堆转储结果


Oracle JRockit Mission Control

运行 Oracle 融合中间件及其提供的 Oracle JRockit JVM 时,无需进行其他安装即可使用 Oracle JRockit Mission Control。

和 VisualVM 一样,从 JRockit 控制台开始进行分析。该控制台使用 Used Java Heap、Used Physical Memory、CPU Usage 和 Live Set 量表以及 Memory 或 Processor 使用情况图形来显示 JVM 当前状态的概要信息。可通过 Memory、Threads、Runtime、Exception Count 或 Memory Profile 选项卡进一步深入了解应用程序配置文件。


Oracle 融合中间件中的性能调优工具概述
图 8 Oracle JRockit Mission Control 控制台


Oracle JRockit Runtime Analyzer (JRA) 现已完全集成到 Mission Control 中,可以用它来根据需要记录应用程序的运行时行为。这不需要特殊的技巧,如内存模块更换、结合或特定共享库方面的技巧。这会带来 1-2% 的小开销。

通过 JRA 可获得应用程序的一个快照。其中包括速度较慢的方法、内存使用情况、所有现有对象、可能的优化方法以及阻塞线程。


Oracle 融合中间件中的性能调优工具概述
图 9 Oracle JRockit Mission Control - Top Hot Methods


Memory Leak Detector。为了发现可能的内存泄漏情况,可以使用 Memory Leak Detector。该工具须应请求才能启动,但会立即显示可能的内存泄漏的趋势。一会儿的功夫,您就会发现实际的泄漏并能够对可疑类进行检查。


Oracle 融合中间件中的性能调优工具概述
图 10 Memory Analyzer — 趋势分析显示可能的内存泄漏。


总结

Oracle 融合中间件附带了一个极好的工具集,用于对可疑应用程序行为进行分析。这些工具主要用于反映即席使用情况,并非用于连续监视。另外,为了全面了解所有组件的情况,需要一个更为全面的视图 — Java (AD4J) 应用程序诊断或 Oracle 实时用户体验会是好的选择。

如果需要对应用程序进行分析,则必须使用模仿引发问题的应用程序配置文件的测试用例。经常运行这些测试用例以全面了解您的应用程序。

对应用程序进行调优时,在每步之后执行这些测试并评估其影响。如果程序并未按照预期工作,返回并尝试进行另一次调优。这需要时间,但最终您将获得一个针对您应用程序配置文件的调优良好的环境。