在生产中测量J2EE应用性能

J2EE性能测量

     性能只有在你决定测量性能的时候性能才是重要的。但一些人发现在测量性能的时候,很难确定需要测量哪个度量值,而且就算他们手头上有了这些信息之后也不知道该怎么办。结果导致了很多人开始竭尽全力地获得所有相关信息。这当然也导致了系统负载过重和获得一些看起来没有意义的信息。在这样的情况下,一些人完全放弃了测量,开始凭着他们的直觉对系统性能调优。

我们当然不能这么干,而应该系统地并且一步一步地对它进行测量。首先,理解为什么要测量性能和通过这些工作你想达到一个什么目标。如果你没有一个目标,那么就没有办法去完成了。

     接下来你需要理解你测量的东西和它们的意义。这可能需要创建一个模型用于跟踪你的数据。只有通过结合数据和模型,你才能获得有价值的信息。例如,预报天气需要一些数据:气温,湿度,大气压力等等。即使我知道它们的每一个值,如果我没有该地区的气候模型我还是不能预报那个地区的天气情况。原始度量值不易理解,在一个有意义的模型中度量值会更易于理解。

 

测量的变量

     让我们开始看看我们的模型需要收集那些度量值信息。我们需要理解J2EE系统一些最基本的东西是:

     反应时间(R)

     吞吐量(X)

     资源利用率(U)

     服务请求(D)

     反应时间用于测量完成一个特定请求需要花费多少时间。它是一个非常重要的度量值因为它是用户体验的一个指数。尽管这样,你必须确保你理解你测量的是什么--系统级的反应时间和Java组件级的反应时间完全不同(因为系统级包括像队列时间这样的变量)。

    它同时也是不容易测量的度量值,因为它比其它的度量值更容易变化。因此你必需了解反应时间的分布。如果应用对你大部分用户的反应时间是2秒钟,而对10%用户的反应时间却是10秒钟,在这种情况下,你必须知道这个反应时间的分布,才能精确地评估该问题和解决它。这就要测量它们的反应时间并且得到它们的标准偏差,理想的情况是用一个柱状图把反应时间的分布显示出来。

     吞吐量指出系统在一段时间内能执行的交易量。它是系统处理负载能力的一个很好的指数,并且通常跟反应时间结合在一起。由于它不是以用户为中心的测量,所以对于一些非交互的系统或批处理工作,它是最值得考虑的。

     资源利用率是用于测量系统特定元素被利用了多少。这个度量值是系统的最底层情况的一个指数,因此对于容量规划是有用的。它也是非常容易理解的度量值,许多人通常都是从处理器和内存的利用率开始入手的,但它不是测量系统性能中最有用的。

    我们发现更多使用的是处于请求中的资源。我们使用称为服务请求(D)的计算度量值显示特定资源或服务将怎样被利用。服务请求用以下公式计算:

    D=U/X

    这给了我们一个比较清晰的资源利用率,对于吞吐量是规范化的。

 

相互关联的度量值

     上面这些度量值之间都有关系,理解它们的关系是创建J2EE性能模型重要的第一步。为了清楚理解它们,我们能够以图表的形式画出这些关系(见下图)。

J2EE性能

    通过这个图,我们可以更清楚看到一些东西。我们注意吞吐量(X)和反应时间(R)经常是成正比增长的。在实验室设置中,或者对于非交互的应用,我们通常将想获得最高的吞吐量。对于用户驱动的生产环境,我们通常想最大化吞吐量,而保持大部分请求时间低于或等于某个反应时间。例如,当保持95%的请求反应时间等于或少于2秒的时候,我们可能想最大化我们的吞吐量。由于这些限制,我们可能发现我们能够达到每秒100个交易的最大吞吐量。

     细看这个图,我们发现资源利用率通常控制着系统行为。这里有一个资源论点,它们认为资源竞争导致了吞吐量的急剧下降和提高了反应时间,吞吐量下降的量和增加的反应时间量是相同的,形成了扣环图。扣环图引起应用性能的服务下降,因为系统花费大部分的时间管理资源竞争而不是服务请求。创建一个系统性能模型看你的应用中这三个度量值是怎么个情况是很重要的。你也想知道:哪个度量值引起负载飙升以及这个度量值的精确值?知道了引起应用负载飙升的值对于在产品监控工具中设置报警值是非常有用的。

 

J2EE系统的一个模型

     确定了测量的度量值,我们现在准备开始把这些数据放到我们的J2EE模型中。图2显示了J2EE系统的样例模型:

J2EE系统模型

     我们看到J2EE系统由四个主要过程组成的:客户处理,包括发起的请求和这些请求可能绑定的会话;执行管理,请求被指派到执行线程前排队等候的地方;应用,包括所有标准J2EE组件的代码;服务,包括了常用的元素,像JDBC和JMS,也有在你的应用和外界之间的连接。当然,所有这些元素都运行在JVM中,而JVM则使用操作系统资源如处理器CPU,内存,物理磁盘和网络连接。

     我们现在能够看到怎样在每一层上测量前面讨论过的度量值。我们需要测量和理解反应时间在各个层中的分布,这些层包括客户请求和处理层,应用代码层(在组件,方法或语句层细节中),还有像JDBC那样服务。在客户处理层中吞吐量是最重要的--我们必须知道我们的系统能处理多少用户负载。在系统中资源利用率是通过很多不同点(操作系统,执行线程,服务等)来测量的,所以我们能关联这些信息并且看到系统中不同元素是怎么互相影响的。

 

测量的开销

     天底下没有免费的午餐。在任何时候,当你实时地测量这些度量值时,你总会给系统增加一些负载。通过了解由于我们测量引起的负载,我们将能够在打算获得的信息量和可能增加的负载之间作出明智的选择。测量这些负载的最好方法是使用前面提到过的服务请求来计算。

在创建系统性能的准确模型时,必须理解在测量时产生负载的影响。J2EE应用是由一些相互联系的系统组成的,并且这些系统在运行时有轻微的不同。处理它的唯一办法是确保锁定你能锁定的一切东西--你不想你的性能测量由批处理任务组成,这些批处理任务会在你的服务器中的某一台突然启动。定期的重做基准测试也是一个好办法。这将确保你很快意识到系统性能的突然下降,性能突然下降会使你的数据无效。

 

测量技术

     现在我们理解了需要从系统中析取的那些度量值,并且开始把它们一起放在J2EE性能执行环境的智能模型中,下一步应该看看怎么样能够有效地收集数据加到那个模型中,使之有意义。

这里有一些地方贯穿着J2EE系统,在那里我们能够收集度量值(如下图所示)。

J2EE

    从客户开始,我们都知道测量客户请求的反应时间是非常重要的。这里有两种方法用于测量客户请求,通过编写浏览器脚本或者使用合成的事务。

     浏览器脚本通常通过在用户下载HTML页面中的JavaScript实现。这是对用户体验的最好测量,但也存在一些明显的困难:很难测量所有客户的可靠性;对于这些页面,脚本代码的部署和维护变得困难和乏味。

     由于这些缺点,更为常用的作法是使用合成事务测量客户的反应时间。这是通过一个进程向系统提交合成的用户事务。这些事务很容易测量并且能得出一个比较准确的用户体验近似值。当然,该提交进程通常或在防火墙外或在防火墙内,因此不可能提供更广泛的网络影响的准确报告。而且,创建逼真的合成事务需要掌握用户与网站交互的很多细节知识,和准确地模拟这个交互的耐心。尽管如此,这些合成事务控制着系统的运行,将对这些问题产生很大的影响,因此需要执行更加复杂的事务并且需要更精细地控制,包括数据采样的时间,向系统提交的事务数量和从系统收集的数据量。

     操作系统度量值是大多数人所熟悉的另一个区域。当然,这些度量值将从贯穿了J2EE系统的机器中收集。要创建你的J2EE系统准确模型,必须理解系统的各个等级中CPU,内存和磁盘使用变化的形式。尽管如此,为了把这些数据加到模型中,你必须能够准确地把系统度量值信息,应用容器和应用代码数据在特定的时间间隔内及时关联起来。只有这样做,你才能描画出应用、应用服务器容器和底层系统之间复杂的交互图。

     也能够从其它系统如web服务器和数据库中收集到度量值,可以把它们跟前面讨论过的操作系统度量值一样对待。不幸的是,没有这种度量值的标准,每个供应商只提供适合它们产品的度量值接口。

     当你收集和关联你的系统度量值,你也想看看JVM使用的关系。JVM提供的一些信息对大部分应用服务器(一般通过JMX)都是没多大价值。这些信息大多局限于某时刻堆的使用情况。如果你需要更细节的信息,这时你能够求助于JVM Profiling Interface(JVMPI),它暴露了许多细节信息包括对象分配和回收;线程锁和调用栈;方法和每行语句的执行时间。尽管如此,JVMPI有一些明显的缺点。它是非常敏感的接口,引起一些负载在系统上(特别是内存消耗),所以在生产系统中不推荐使用它。而且为了打开和关闭该接口,还需要重启JVM。它也没提供特定于你的应用的信息--这意味着在复杂的环境中像J2EE,还得经过一顿筛选才能得到需要的信息。

     应用服务器度量值通常跟主要供应商提供的有关。虽然每个服务器有轻微的差别,但它们通常都包含以下:

     用于Servlets,JSPs和EJBs的反应时间和利用率

     用于EJBs,JDBC连接和其它服务元素的缓冲

     像JDBC,JMS,JCA和JNDI那样服务的利用率

     事务信息

     线程/队列数据

     JVM度量值

     一般的配置信息

     这些度量值非常重要,因为它们能提供用于完成J2EE性能模型的反应时间,吞吐量和资源利用率信息。而且,你要是具有了收集整个或者部分系统数据的能力,那就意味着在分析中获得一些弹性。当然通常是这种情况,使用强大的和灵活的系统,操纵大量数据是麻烦的事,特别以前它没有默认绑定具体的应用事务或请求。

     BEA's WebLogic通过JMX暴露它的度量值,这让你作为开发者访问它们。这个基于标准的方法使你通过接口能够得到访问这些数据的权限,比通过WebLogi控制台还容易。WebLogic度量值本身是很强大的,尽管如此,它们有一个值得注意的缺点,那就是缺少用于EJB方法反应时间的信息(这些信息是针对Servlets)。

     IBM's WebSphere在4.x版本中使用它们私有的PMI接口。它(包括了例如EJB方法反应时间)趋向于提供比WebLogic有点更全面的度量值,但代价是牺牲了J2EE的灵活性(它不是基于JMX的)。对于WebSphere 5.x,通过PMI或者JMX都可以得到度量值。WebSphere接口的另一个好的特性是你可以控制获得的细节信息。PMI能够设成以下五个等级中的任一个:None;Low;Medium;High;Maximum报告备份数据。

     从应用服务器中收集这些数据通常不是产生大量负载的原因。尽管你不能关闭Mbean数据的收集,这些收集是在提供JMX度量值的WebLogic上进行的,但因此产生的负载可以不用考虑,除非你进行一些远程Mbean查询。WebSphere的PMI接口允许你关闭掉数据的收集,但除了这些之外,我们对各等级的测试中发现在负载上没有什么不同。不值得这么做,尽管如此,有一些内存负载跟PMI数据收集是相关的--如果你使用PMI,请确定你有足够的多余内存供它使用。

     Oracle's application server通过它的DMS servlet提供度量值。这个servlet返回一个文件,该文件含有性能度量值的层次图,有XML或者属性-值两种表示形式。这些数据包括关于JVMs,JServ,JDBC和EJB的性能信息。这个数据集不像WebLogic或WebSphere那么完整。例如,它没有EJB缓冲或者池的数据信息,也没有执行队列的数据信息。不管怎样,一些核心的数据是可以得到的,而且由此产生的负载很低。

     Jboss application server通过JMX提供它的性能度量值。它的度量值集合是相当完整的了,并且包括Tomcat和应用服务器上面的数据。也可以得到如活动的线程,EJB池和缓冲等上面的重要度量值。

     使用网络嗅探器也可以获得有价值的信息。它是通过还原传过来的协议来工作的。这个几乎没有接触的交互不产生负载。它提供的这些数据极其有价值,但它大部分通常是非常复杂和原始,需要用户那边大量的专门技术把它们转换成能理解的信息。这种解决方案往往是昂贵的,因为可以获得大量的有价值数据,产生的负载也很小。如果能够付得起这个费用,并且你能够有效地使用它们提供的信息,这通常是个好的投资。

 

应用代码工具

     数据收集的最后一个难题是应用代码工具。这里有两种代码工具:定制工具和自动化工具。定制工具完全是由开发者处理的。它们把测试代码插入到Java代码或产生字节码,用于收集它们想要的度量值(通常是J2EE组件级-或者方法级-时间信息)。这时这个信息发送到中心的记录器,这个记录器需要开发者编写。这是非常复杂的工作,并且大多数公司愿意通过购买事务的J2EE诊断工具避免这个问题。

     自动化工具能够通过很多方式工作,但不管它怎么工作,它都通过自动添加性能测量代码到应用类产生的字节码,节省了时间。这样带来的好处是性能工具供应商能够花费大量的时间和精力去最优化工具链的每一个环节。这意味着比定制工具方案明显地减少负载。自动化工具也能够很快地和容易地应用在任何一个应用上,而定制工具需要开发者那边花费大量的时间和精力添加需要的字节码。

     自动化工具基本上有两种执行方式--静态的pre-instrumentation和类加载器工具。pre-instrumentation包括为应用产生JAR文件,并且把测量代码添加到某个类中。这个可能有问题,尽管这样,当它要求客户预先确定它们想要监控的东西--这经常意味着它们将只能看自己希望出现问题的地方,并且因此漏掉了自己不希望出现问题的地方。

     执行自动化工具的另一种方式是通过直接地测量Java类加载器。在这环境中,用于执行测量的字节码被自动地添加到已编译的类中,就像类加载器那样加载它们。这意味着没有pre-instrumentation步骤,并且不需要花费力气预先确定需要测量的类。最后,这个方法易于携带,并且可以用于相同类的多个版本。

     不过怎么收集这些数据,它提供非常好的视图查看你的应用代码--有一些是其它度量技术不能做到的。通常你能够在J2EE组件,类或方法这些粒度上获得以下度量值:

     调用次数

     方法执行时间(专有的时间)

     方法执行时间加上该方法调用的所有其它方法所花的时间的总和(累积时间)

     例外抛出

     远程方法调用(RMI)中的字节传输/序列化

     栈信息

     对于快速且准确地诊断一些代码相关的性能问题,这些深入应用信息是必须的。它能帮助你确定应用在哪儿被滥用了或者崩溃了,也很容易分离方法级别瓶颈,这可能危及你的SLAs。

 

J2EE的应用性能管理工具

     正如前面讨论的,运行定制的J2EE应用需要优化终端用户性能,减少故障时间以及满足严格服务等级。不管怎样,采用反应型应用管理方式会消耗金钱和时间。

J2EE

     Quest Software为J2EE平台提供了应用性能管理包(APM),让IT团队--包括开发者,QA职员,应用管理者和其它应用支持者--在开发,测试和生产中的任一个阶段都能发现,诊断和解决性能问题。

     uest用于J2EE平台的应用性能管理包能够通过应用栈,深入到代码级别分离和识别问题,提高员工的生产力,质量和效率,消除全盘搜索J2EE应用和数据定位问题所需要的昂贵费用。Quest用于J2EE的应用性能管理包提供以下功能:

     服务等级管理

     基于服务模型和用户反应时间,通过分离性能问题改善员工效率。

     应用服务器诊断

     快速识别和解决由资源瓶颈和服务器配置引起的性能问题。

     深入的事务诊断

     使用Quest的Tag and Follow技术执行基于事务的深入诊断,识别有问题的方法或者引起性能问题的SQL。

     应用代码剖析

     使开发者能够快速解决不合适的java代码行,改善最终用户的反应时间。

     终端用户监控

     从最终用户的观点监控他们实际的体验,用于识别冲突和低下的性能,确保使用应用的客户有一个好的体验。

 

结论

     这篇文章的目的已经解释主要的度量值和怎样收集它们到J2EE性能模型中。不幸的是,这里没有唯一的模型用于所有的J2EE系统--每个系统在一定程度上都是定制的,因此必须单独处理。作为性能分析者,你必须系统地分析应用。

从确保应用管理者清楚他们需要的性能等级开始。一旦你理解了需要什么等级的性能,并且知道怎样测量那些性能,你将必须确定需要哪些信息用于评估现在的系统性能。在这儿,你将需要在想要的信息量和因此带来的负载量之间作出个权衡。从这一点,你能够继续确定怎样收集需要的信息,和哪种性能模型适合你的系统。

     所有这些需要精力--你必须通过锁定环境经常地控制系统变量,并且不断重复基准测试确保你是在一个稳定的基础上测量的。这些努力是有收获的。如果遵从这些方针和常识,你将能够从中解放,并且支持应用超出它的性能期望,使之更稳定。