关键统计指标的测量
作为诊断系统性能问题的权责人员,您必须持续跟踪应用程序健康度的关键统计指标。您能够测量到什么?又有什么工具可以提供帮助?具体如下
■ 内存的总体使用状况。多个不同层级(如JVM堆和操作系统)的内存使用状况。Java堆事件探查器对堆的使用状况清晰可见;top,vmstat以及 Windows Perfmon等工具对操作系统层级的内存使用状况实时可见。在您的JVM中打开可用的-verbose:gc选项,便能够轻松查看Java堆的汇总视 图。
■ CPU时间。包括CUP时间汇总(通过top等功能实现)、每个组件占用的CPU时间、每种方法占用CPU的时间(数据可通过Java事件探查器获得)
■ 实际运行时间(又称作“真实”时间)。 包括每个事务、每个组件和每种方法的实际运行时间。可参照统计平均值,也可分别统计单个数据点的数值。Java事件探查器能够提供部分此类数据,尽管如此,采用适当的应用程序监视解决方案才是您的最佳选择。
■ 内部资源。包括已分配的内部资源数量、使用中的内存资源数量,等待的客户数量、获得某种资源的平均等待时间、某种资源的平均使用时间、使用某种资源完成工作请求的平均时间。应用服务器通常会提供这些数据的最小可视化视图。
■ 外部资源。包括已分配的外部资源数量、使用中的外部资源数量、等待的客户数量、平均等待时间以及由外部系统直接测量的数据(例如外部系统视图,表征其如何 快速地完成工作请求)。值得一提的是,运行应用服务器的操作系统和硬件也是“外部资源”(例如,您是否使用过多进程和端口?)。对这些资源进行测量有两种 形式:在JVM内部测量提供该资源的桥接层;用外部资源自带的工具对其本身进行测量。
■ 网络资源使用状况。网络嗅探器等网络设备提供带宽使用率、响应的时间延迟等数据,操作系统的本地工具(如netstat)也能够提供上述数据。
■ 系统状态。包括Thread- Dumps的使用、日志文件、追踪文件以及堆栈追踪等。深入分析时也可引用调试器中查看到的变量的值。
实验工作
很多时候,在一次标杆测评中获得的数据并不足以揭示答案。完成系统诊断的难点在于:您要以有限的预算同时进行试验以及实验工作。应该进行何种试验?又需要观察或修改哪些变量?这正是以下要回答的问题
■ 尝试观察系统行为随时间的变化。在恒定负载条件下观察测量值随时间的变化趋势。这个过程短则一小时,长则数天。譬如您可能观察到内存使用率随时间的增加而 增长。当内存使用总量达到上限时,JVM用于碎片收集的时间、操作系统颠簸及内存页抖动的时间都会增加,从而使得您的用户事务处理的总体响应时间延长。若 GC进程崩溃,全部碎片的收集耗时过长,将导致任何正在进行的事务处理出现超时和异常。此时就必须全面查找资源或内存泄漏。
■ 尝试改变系统负载状况。选择3到4个工作负载(如10个、50个或100个用户),收集各用户数据。图示化表示上述负载的测量值,比如您会发现:即使您的 帐户登陆Servlet组件的响应时间少于50毫秒,负责销售税计算的EJB组件的运行速度还是随用户数目的增多直线递减。如果负载状况下该EJB组件性 能的差异基本能够解释负载状况下总体响应时间的变化,那么就需要对该组件进行深入分析。当然也要尝试将该负载退出,看看系统能否恢复正常 。
■ 尝试将大系统划分成若干规模较小的子系统,然后再依次测试。选择单条或多条坐标轴划分系统。最基本的是系统层(包括负载均衡器、网络服务器、应用服务器、 后台系统等)。其它情况也可能包括用户帐户、内部组件、事务类型以及单个页面。以用户帐户为例,在A用户的帐户下运行某些负载,然后在B用户的帐户(A、 B最好存在较大差异)下运行某些负载,比较两组数据的不同测量值;或者依次测量您的后台系统,对应用程序中频繁调用后台系统的地方进行重点测试。根据您想 验证或推翻的推断的不同,可取用不同的坐标轴划分系统。建议如下
.. 如果某个用户的登陆看似会引发某种问题,则可能是由该用户帐户的配置文件(如载入2000个采购订单的完整历史记录)引起,也可能是由该用户使用该系统的方式(如页面访问的顺序、某个用于检索个别文档的查询字符串)引起。
.. 如果您使用的是群集系统,不妨以单台设备为单位划分系统。有时无论做何努力,列表框中始终没有最新的应用服务器补丁或操作系统补丁(这些补丁能够极大地改 善系统性能)。除此之外,还需留意负载均衡器或守护进程,查看其是否均衡分配工作负荷,是否及时响应入站请求。
诊断:测试您的推断
至此,您应当拥有足够的信息去推断引起性能瓶颈的原因。为了确认推断正确与否,有针对性地对多个备选推断进行筛选,就需要分析更多的信息,对系统进行附加的标杆测评。这里提供部分建议以供参考。
■ 通过查看CPU总体使用率,可将编码缺陷(不论是应用程序组件还是桥接层本身)和瓶颈(包括内部或外部瓶颈)准确区分开来。当CPU总体使用率不随负载状况的变化而改变,但系统的总体响应时间却随之变化时,则说明应用程序大部分时间都处于等待状态。
■ 某个外部资源看似出现了问题,并不代表您能够立即把责任归咎于它。譬如,桥接层本身出现问题或者出现某个联网问题时,数据库看似运行缓慢,实则不然。举一 个更为简单的例子,您的数据库访问要求可能并不合理(如用户每次登录需将两百万行数据插入3个表单)。因此有必要不时地将桥接层(如JDBC驱动程序)的 响应时间与系统资源提供的时间或专用工具(如DBA Studio)的本地时间相比较。
■ 架构图表有助于了解系统内部的整体交互情况。值得一提的是,示意图并不是真实的区域版图。编码缺陷或对架构意向的错误理解都有可能使系统的实际行为偏离期 望值。性能监控工具提供的硬数字比一份声称“每个用户事务只发送一条SQL语句”的文档更加具有信服力。
■ Occam’s Razor原理(即“如无必要,勿增实体”)。现在来讨论您的备选推断:一是在某个拥有两百万行代码的系统中有一个存在编码缺陷的组件 ,该组件上周才与系统整合;二是JVM的即时编译器正在生成有缺陷的机器码,严重破坏了该变量的内存完整性。除非您能够拿出具体数据来证实(我曾经亲眼见 到第二种情况的发生),否则就应更加深入全面地分析第一个推断。虽然拜占庭故障(Byzantine Failures)是J2EE系统更容易出现的故障模式,但却不要因此丧失您的判断力(即测试应从更为简单的推断开始)。
■ 日志文件中没有错误不表示错误不曾发生。出于很多原因异常未被写入日志,比如可能由于程序员认定某些状况“永远不会发生”而忽略了那些异常状况;也可能是由于某个组件的自动故障恢复机制,因而第一次故障未被记录。