热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何诊断J2EE系统中的性能问题

如何诊断J2EE系统中的性能问题时间:2004-12-14作者:JohnBley浏览次数:本文关键字:诊断,J2EE,性能,测试,瓶颈文章工具推荐给朋友打印文章现在要求您诊断We

如何诊断 J2EE 系统中的性能问题

时间:2004-12-14
作者:John Bley
浏览次数: 
本文关键字:诊断, J2EE, 性能, 测试, 瓶颈
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章
现在要求您诊断  WebLogic J2EE 应用程序中的性能问题。因为 Java 系统是如此复杂,所以诊断  WebLogic J2EE 应用程序中的性能问题就有点像诊断疑难杂症。
为了正确地找到问题所在,您需要对症状有全面了解,要做好准备进行大量研究工作,最后您需要制定正确的治疗方案。本文讨论了 J2EE 应用程序性能问题的一些最常见类型和它们产生的原因,以及如何正确地诊断和消除它们的推荐指导原则。


症状
   WebLogic 应用程序性能问题的症状是什么?您看到的症状可以指导您在所有可能的问题中进行搜索。请准备一个笔记本并开始向人们调查。试着把对问题根本原因的推测和假设与系统行为的实际证据分离。下面是一个常见症状集的列表:
  • 持续缓慢:应用程序一直特别慢。改变环境因素(负载、数据库连接数量)对整体响应时间的改变很小。
  • 随着时间推进越来越慢:系统运行时间越长(负载相对均衡不变的情况下),就变得越慢。有可能是(最后)达到了某个阈值,系统被锁定或者由于大量错误而崩溃。
  • 随着负载增加越来越慢:每增加一个额外用户,应用程序就变得越慢。如果用户离开系统,系统就“冷却下来”,恢复正常。
  • 零星的挂起或者异常错误:偶尔(可能由于负载或某些其它原因),在页面无法完成或者出现追踪到异常和堆栈的错误页时,用户会看到挂起的情况。挂起的数量可能不同,但总是无法完全消除,甚至在强化 (“burn in”) 期间之后也是如此。
  • 可以预见的锁定:首先出现一些挂起或错误,然后加速出现,直到系统完全被锁定。通常这些问题可以通过“重新启动来管理”的方式解决。
  • 突然混乱:系统一直运行正常,相当一段时间里(可能一个小时,也可能是三天)性能都还差强人意,但是“突然某个时候,根本没有任何原因的”,系统开始出现大量错误,或者被锁定。

为什么问题诊断如此复杂?
  对于 WebLogic 应用程序的某个具体应用模式来说,没有既定的公式可以用来推导出它的性能(在严格的实时工程当中,速度单调分析这类技术确实可以做这项工作,但是在本文里 还是让我们忘记它吧)。网络上是否存在另外一个系统正在密集使用一个共享的后端服务,对于实际产生的性能有很大影响。性能也许还取决于 JDBC 驱动程序版本和数据库的正确匹配。也许开发人员三年前写的一些代码恰巧在这个时候才出现特定类型的异常,而您急切需要的解决问题回馈,却恰恰包含在这个异 常里。 
  从本质上说,典型业务系统的性能是由成千上万交互的变量和决策共同作用的结果。就像人体一样,有太多连锁着的部分和过程,所以很难理解系统的整体。因此我们进行了简化,并求助于拱形模式。 

疾病
  您看到的症状的根本原因是什么?它是初级流行性感冒或者是肺炎的开始吗?是应用程序内部的底层问题还是它所在的 JVM 外部的问题?请参阅表 1 中应用程序性能低下的一些最常见原因。

表1

毛病 描述 症状 原因或治法
线性内存泄漏 每单位(每事务、每用户等)泄漏造成内存随着时间或负载线性增长。这会随着时间或负载增长降低系统性能。只有重启才有可能恢复。 随着时间越来越慢
随着负载越来越慢
虽然可能有多种外部原因,但最典型的是与资源泄漏有关(例如,每单位数据的链表存储,或者没有回收的回收/增长缓冲区)。
指数方式内存泄漏 双倍增长策略的泄漏造成系统内存消耗表现为时间的指数曲线 随着时间越来越慢
随着负载越来越慢
通常是由于向集合(Vector,HashMap) 中加入永远不删除的元素造成的。
糟糕的编码:无限循环 线程在 while(true) 语句以及类似的语句里阻塞。 可以预见的锁定 您需要对循环进行大刀阔斧的删剪。
资源泄漏 JDBC 语句,CICS 事务网关连接,以及类似的东西被泄漏了,造成对 Java 桥接层和后端系统的影响。 随着时间越来越慢
可以预见的锁定
突然混乱
通常情况下,这是由于遗漏了 finally 块,或者更简单点,就是忘记用 close() 关闭代表外部资源的对象所造成的。
外部瓶颈问题 后端或者其他外部系统(如鉴权)越来越慢,同样减缓了 J2EE 应用服务器和应用程序 持续缓慢
随着负载越来越慢
咨询专家(负责的第三方或者系统管理员),获取解决外部瓶颈问题的方法。
外部系统 J2EE 应用程序通过太大或太多的请求滥用后端系统。 持续缓慢
随着负载越来越慢
清除冗余的工作请求 ,成批处理相似的工作请求,把大的请求分解成若干个更小的请求,调整工作请求或后端系统(例如,公共查询关键字的索引)等。
糟糕的编码:CPU密集的组件 这是 J2EE 世界中常见的感冒。一些糟糕的代码或大量代码之间一次糟糕的交互,就挂起了 CPU,把吞吐速度减慢到爬行的速度。 持续缓慢
随着负载越来越慢
典型的解决方案就是数据高速缓存或者性能计数。
中间层问题 实现得很糟糕的桥接层(JDBC 驱动程序,到传统系统的 CORBA 连接),由于对数据和请求不断的排列、解除排列,从而把所有通过它的流量减慢到爬行速度。这个毛病在早期阶段很容易与外部瓶颈混淆。 持续缓慢
随着负载越来越慢
检查桥接层和外部系统的版本兼容性。如果有可能,评估不同的桥接供应商。如果重新规划架构,有可能完全不需要桥接。
内部资源瓶颈:过度使用或分配不足 内部资源(线程、放入池的对象)变得稀缺。是在正确使用的情况下加大负载时出现过度使用还是因为泄漏? 随着负载越来越慢
零星的挂起或异常错误
分配不足:根据预期的最大负载提高池的最大尺寸。过度使用:请参阅外部系统的过度使用。
不停止的重试 这包括对失败请求连续的(或者在极端情况下无休止的)重试。 可以预见的锁定
突然混乱
可能就是后端系统完全宕机。在这里,可用性监控会有帮助,或者就是把尝试与成功分开。
线程:阻塞点 线程在过于积极的同步点上备份,造成交通阻塞。 随着负载越来越慢
零星的挂起或异常错误
可以预见的锁定
突然混乱
可能同步是不必要的(只要重新设计),或者比较外在的锁定策略(例如,读/写锁)也许会有帮助。
线程:死锁/活动锁 最普遍,这是您基本的“获得顺序”的问题。 突然混乱 处理选项包括:主锁,确定的获得顺序,以及银行家算法。

测量关键的统计指标
  当您负责诊断问题的时候,您应当能够跟踪关于您的 WebLogic 应用程序健康情况的关键统计指标。您能测量什么?有什么工具可以提供帮助呢?

  • 使用的全部内存:在不同级别上 (JVM 堆栈,操作系统),Java 堆栈 profiler 对堆栈的正确使用提供了可见性;像 top ,vmstat 以及 Windows Perfmon 这样的工具在操作系统级别上为内存使用提供可见性。察看 Java 堆栈的一个简单的聚合视图,请打开―verbose:gc 开关(如果在您的 JVM 上可以使用的话)。
  • CPU 时间:合并(可以通过使用 top 等方式得到)每个组件或每种方法。其中某些指标可以通过 WebLogic 管理控制台得到。也可以通过 Java profile 使用它们。
  • 计时 (a.k.a.“实” 时):每事务,每组件,每方法;可以按统计平均值或单独的数据点查看。Java profiler 可以产生一些这样的数据,但是使用程序监控解决方案可能是您的最佳选择。
  • 内部资源:分配的数量,使用的数量,等待的客户数量,获得资源的平均等待时间,使用资源平均消耗的时间,使用资源完成请求工作时使用的平均时间。应用程序服务器通常会给出这些数字的最小可视性。
  • 外部资源:分配的数量,使用的数量,等待的客户数量,平均等待时间,加上对这些外部系统的直接测量(例如查看它能多快完成请求的工作)。不要忘记运行应用程序服务器的操作系统和硬件也是“外部资源”-例如,是否您使用了太多的进程或端口?可以用两种形式测试这些资源―从 JVM 内部测试提供资源的桥接层,用外部资源本身的工具测量外部资源。
  • 网络应用:带宽使用,延迟。虽然操作系统自带的工具(例如 netstat)也有助于做这些工作,但是网络嗅探器设备可以深入了解这些信息。
  • 系统状态:用线程清除,日志和跟踪文件,堆栈跟踪等等。或者在更深层次上,就像调试器中查看的那样使用变量的值。

实验工作
  有的时候,在一次标杆运行中获得的数据,不足以揭示答案。那么找到答案的机会就在于您还有些有限的预算,可以运行试验或者做实验工作,来完成诊断。您可以运行什么类型的试验呢?您可以修改、观察什么变量呢?

  • 尝试观察系统行为在一段时间上的变化。应用一个衡定的负载,并观察您的指标随时间发生的变化。您可能会看到某些趋势,短则一小时就可看到,长则二三天。例如,您可以看到内存使用随着时间而增长。随着使用的内存数量达到上限, JVM 花在搜索垃圾上的时间和操作系统花在分配内存页面上的时间开始减少用户事务的整体响应时间。当抛开 GC 的时候,垃圾搜集的整个过程可能过长,从而造成执行中的事务超时和异常。现在可以开始查找资源泄漏或内存泄漏了。
  • 尝 试在系统上改变负载。 采用三到四种工作负载(例如,10个,50个和100个用户),并搜集每个负载的数据。分析一下您对这些负载的测量情况。例如,您可能发现,当您的账户登 录 servlet 的响应时间无论如何都会低于 50 毫秒的时候,计算销售税的 EJB 却随着用户数据的增长,速度呈线性下降。如果这个 EJB 性能在负载下的差异能解释整体响应时间性能在负载下的增长,那么现在就是深入分析这个组件的时候了。谨记一定还要把负载恢复原状,并查看系统是否复原。
  • 尝试把系统分成小单元,针对每个单元轮流进行压力测试。 选择一个或多个坐标系对系统进行划分。主要的一个是系统面上的层:负载均衡器、Web 服务器、WebLogic Server,以及后端。其它示例包括用户账户,内部组件,事务类型,以及单独的页面。假设您选择了用户账户。在用户 A 的账户下运行一些负载,然后再在用户 B 的账户(应当非常不同)下运行某些负载;比较两次运行间不同的测量结果。或者,轮流选择您使用的后端系统,分别对使用每个后端系统比较重的应用程序组件进行压力测试。具体要选择哪个坐标进行划分,完全取决于您要证明或者否定哪个假设。下面是一些具体想法:
      - 如果某个用户的登录看起来造成了问题,那么有可能是这个用户账户档案(例如,装入 2,000 个订单的完整采购历史),或者可能是他使用系统的方式(例如,页面访问的顺序,或者他用来查找某个文档的查询字符串的正确性)。
      - 如果您使用的是一个集群系统,请尝试以单台机器为单位划分。尽管尽了最大努力,有的时候还会有一些机器没有安装最新的应用服务器或者操作系统补丁,这就会 造成不同的性能特征。而且,还请注意负载均衡器,或者保姆进程,查看它们是否公平地分配了工作并跟踪了进入请求。

诊断:测试您的推测
  在这个时候,您应当已经有了足够的信息,可以形成关于性能瓶颈原因的推测了(请参阅表 1)。为了验证您的推测是否正确或者在多个备选的推测之间进行筛选,您需要分析更多的信息或者在系统上运行更多的标杆测试。这里是一些可以帮助您的指导意见:

  • 区分糟糕的编码(或者是应用程序组件或者是桥接层)和瓶颈 (内部的或外部的),请查看整体的 CPU 使用情况。如果它在负载下没变化,但是整体响应时间变化了,那么就是应用程序花费了它的大多数时间来等待。
  • 仅仅是因为好像是外部资源的问题,不代表您就可以立刻把责任推到资源上。 例如,分层或联网的问题,也能造成数据库看起来很慢,虽然实际上它并不慢。或者,更简单一点,您对数据库的请求可能是不合理的(每次用户登录的时候,都要进行三个表之间的 200 万行记录合并)。应当一直把桥接层的响应时间(例如,JDBC 驱动器)和资源提供的时间或者工具提供的时间进行比较(例如,DBA Studio)。
  • 结构化的图表有助于您理解系统内部的整体交互,但是不要忘记地图并不是领地。.编码错误或者对架构意图的误解,有可能使系统的实际行为与期望的行为不同。请相信性能工作提供的实际数据,而不要相信一个声称“每个用户事务将只会发布一个 SQL 语句”这样的文档。
  • 使用 Occam 军刀。 假设您有两个备选推测,一个是:在 200 万行代码里,有一个编码糟糕的组件,直到上周这个组件才集成进来;另一个是 JVM 的即时编译器生成了糟糕的机器码,破坏了这个变量的内存完整性。除非您有具体的数据来证实,否则(我已经看到了第二种情况发生),请更详细地检查第一个假设。J2EE 系统确实容易出错,但是不要让这一点就妨碍您先测试一个更简单的假设。
  • 日志文件中没有错误不代表不存在错误。 有许多原因可以造成不在日志里写下异常;可能是因为程序员认为某件事“永远不会发生”,于是就排除了这个异常;也可能是因为某些组件可以使用故障恢复机制,所以就没有记录第一次故障。

示例诊断
  让我们来实际研究一个示例。您的 WebLogic 应用程序表现出在负载下越来越慢的症状。您加入的用户越多,系统越慢。一旦消除负载,系统就冷静下来,没有任何后遗症。您对这一主要症状进行测试,发现并得到图 2 所示的以下结果(时间测量针对的是单一典型事务的端到端完成时间)。

表2

负载(用户数) 来回用时(毫秒)
10 300
50 471
100 892
150 1067

应用程序性能在负载下越来越慢

  您形成了几个假设。也许这里的毛病是一个糟糕编码的组件,也许是后端系统的瓶颈。它可能是一个同步阻塞点。您怎样才能分清它们的不同呢?假设您还测试了应用程序服务器在负载运行期间的CPU整体使用情况,并得到了表 3 所示的结果。

表3

负载(用户数) 来回用时(毫秒) 整体 CPU 时间(%)
10 300 30
50 471 33
100 892 37
150 1067 41

问题看起来好像是“等待”瓶颈

  现在看起来,系统不是 CPU 密集型的,这就是说它的多数时间都花在等待上了。那么是它的内部(例如,同步交通阻塞)或外部(缓慢的数据库)的问题?好,让我们假设我们还稍微多搜集了一些数据,如表 4 所示。

表4

负载(用户数) 等待数据库连接的线程数量 JDBC 查询用时(毫秒)
10 2 58
50 3 115
100 3 489
150 4 612


问题是否出在一个缓慢的 SQL 语句上呢?

   现在看起来并不是内部等待数据库连接的瓶颈,相反,好像是 JDBC 查询本身的问题。JDBC 查询不仅随整体事务时间的不同而不同,而且它糟糕的性能还解释了整体性能糟糕的原因。但是,我们还不能完全确定。您仍然还有三个主要的假设要排序:是否数 据库本身慢?应用程序是否对数据库进行了不合理的请求?或者问题是不是出在应用程序和数据库之间的某个层上?您拿出数据库供应商专用的工具,从它的角度查 看响应时间。假设您看到如表 5 所示的数字。

表5

负载(用户数) JDBC 查询计时(毫秒) DB SQL 执行的时间(毫秒)
10 58 43
50 115 97
100 489 418
150 612 589

实际是数据库中的 SQL 语句慢

   如果您没有看到这条信息,那么您可能要返回 JDBC 驱动程序,期待能够发现其中的某些同步问题(请记住,CPU 没有被抑制)。幸运的是,在这个案例里,您已经把具体问题的范围缩小到数据库查询上。找出查询请求是否足够合理,需要一些相关领域的知识,需要熟悉系统, 但是在这个案例里,它也许就是发现查询把非索引字段和外键进行了比较。您和 DBA 协作,它修改索引方案,让查询变得更快,而您则找到了您的药方。 

结束语
  诊断 WebLogic J2EE 应用程序的性能瓶颈是一个艰苦的旅程。请随时保持清醒,把事实与推测分开,总是用实际的证据来确认您的推测。我希望给您带来了思考和实践问题的一些有用的想法的分类。就像调试,这仍然是一项不明确的艺术,但是深思熟虑会带您走出困境。祝您好运!

原文出处 http://www.sys-con.com/story/?storyid=43024&DE=1
 作者简介

John Bley是Wily Technology 的软件工程师。他有丰富的 Java 编程和架构经验。为了撰写本文,他总结了 Wily 的企业客户的经验,Wily负责管理复杂的 J2EE 环境。


推荐阅读
  • 《我的世界》Java版种子合集:探索多样世界生成
    本文介绍了《我的世界》Java版中用于生成多样化游戏世界的种子代码。这些种子是由一个或多个字符(包括正整数和负整数)组成的值,能够为玩家带来截然不同的地形和环境体验。通过使用不同的种子,玩家可以探索各种独特的地貌、生物群系和结构,从而丰富游戏的乐趣和挑战性。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • Framework7:构建跨平台移动应用的高效框架
    Framework7 是一个开源免费的框架,适用于开发混合移动应用(原生与HTML混合)或iOS&Android风格的Web应用。此外,它还可以作为原型开发工具,帮助开发者快速创建应用原型。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
  • 在《Linux高性能服务器编程》一书中,第3.2节深入探讨了TCP报头的结构与功能。TCP报头是每个TCP数据段中不可或缺的部分,它不仅包含了源端口和目的端口的信息,还负责管理TCP连接的状态和控制。本节内容详尽地解析了TCP报头的各项字段及其作用,为读者提供了深入理解TCP协议的基础。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 本文将继续探讨 JavaScript 函数式编程的高级技巧及其实际应用。通过一个具体的寻路算法示例,我们将深入分析如何利用函数式编程的思想解决复杂问题。示例中,节点之间的连线代表路径,连线上的数字表示两点间的距离。我们将详细讲解如何通过递归和高阶函数等技术实现高效的寻路算法。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 深入解析 OpenSSL 生成 SM2 证书:非对称加密技术与数字证书、数字签名的关联分析
    本文深入探讨了 OpenSSL 在生成 SM2 证书过程中的技术细节,重点分析了非对称加密技术在数字证书和数字签名中的应用。非对称加密通过使用公钥和私钥对数据进行加解密,确保了信息传输的安全性。公钥可以公开分发,用于加密数据或验证签名,而私钥则需严格保密,用于解密数据或生成签名。文章详细介绍了 OpenSSL 如何利用这些原理生成 SM2 证书,并讨论了其在实际应用中的安全性和有效性。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
author-avatar
依love依CENE_790
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有