JBoss AS 7性能调优 (一)
原文: http://www.mastertheboss.com/jboss-performance/jboss-as-7-performance-tuning
调优JBoss应用服务器
虽然许多架构师和软件工程师都同意,约70-80%的应用程序的性能取决于应用程序本身的编码,配置不当的服务器环境可以显著影响你的用户体验,并最终影响到你的应用程序性能。
很多配置元素,可以显著地影响你的服务器的性能,他们中的一些配置值得特别注意:
• JVM 调优
• 应用服务器资源池
• 日志
• 缓存数据
让我们看看每个元素的细节。
JVM调优
Java虚拟机(JVM)中运行的JBoss AS7,在JVM参数的正确配置下可以提供更好的性能。
JVM优化已经发展了很多年,实际上每一个Java的版本都有变化。由于在J2SE的5.0版中,JVM能够提供与您的环境相一致的一些默认的配置(“人类工程学”)。然而,人体工程学(Ergonomics)提供的聪明选择并不总是最优的,用户设置不合适的情况下,性能可能低于你的预期。
基本上, JVM的调优过程可以分成以下步骤:
•选择一个正确的JVM heap大小。它分为一个合适的heap初始值(-Xms) heap最大值(-Xmx).
•选择一个合适的垃圾回收算法。
让我们看看这两个元素的细节。
选择合适的 JVM 堆大小
Java对象在堆上创建,每个堆被分成三个部分,或三个垃圾回收代,被称为新生代( Young generation),年老代( Tenured or Old generation),和持久代( Permanent)。
新生代进一步分为Eden,Survivor 1,Survivor 2这三个空间。当一个对象被首先在堆中创建,它在新生代的Eden空间被创建,并且在随后的新生代GC(minor GC)后,如果该对象存活,它被转移到Survivor 1,然后被移到Survivor 2,直到发生年老代GC(major GC),对象被移动到年老代。
永久代空间有些特殊,它是用来存储JVM中的类和方法的元数据,它也存储了JVM中提供的String池。
为了调整JVM,你应该选择新生代(对象实例化后最初放置的地方)和年老代(存活期长的对象被移到这里)之间的正确比例。
对于大多数应用程序,新生代和年老代之间的正确比例范围在1/3 和1/2之间。
合适的堆最大值可以通过在使您的应用程序加载峰值负载的一段稳定的时间内测试来确定。一旦您已经确定了应用程序所需要内存的峰期,取决于应用程序的性质,你可以增加一个额外的25-40%的内存作为堆最大值。
至于初始堆大小,一个好的经验法则是将其设置和堆最大值相同。这增加了可预测性,避免了需要分配内存时扩展堆,这在生产环境特别有用,而开发者(拥有有限的资源)可能会选择一个更小的初始堆大小。
保持该配置为较小环境的建议配置,也可以作为更大环境的参考:
java -Xmx1024m -Xms1024m -XX:MaxNewSize=448m-XX:NewSize=448m -XX:SurvivorRatio=6
java –Xmx2048m –Xms2048m -XX:MaxNewSize=896m-XX:NewSize=896m -XX:SurvivorRatio=6
调整GC
GC是由Java虚拟机提供的,是从符合垃圾回收的对象中回收堆空间的机制。
一个对象符合GC条件是说,它不是来自引用可到达的任何活动线程或任何静态引用。换句话说,如果它的所有引用都为null,一个对象就符合了垃圾收集的条件。
选择正确的垃圾收集器的算法是一个关键的(但经常被忽视的)因素,有下列几种可用的垃圾收集器:
• Serial collector(-XX:+UseSerialGC): 它使用单个线程并通过停止其他JVM的线程来执行,此收集器适合于较小的应用程序,不建议使用在企业应用程序中。
• Parallel collector (-XX:+UseParallelGC): 它并行执行新生代GC, J2SE 5.0中也可以并行执行年老代GC(-XX:+ UseParallelOldGC)。此收集器适合于多处理器机器和需要高吞吐量的应用程序,同时建议用在产生更多Java堆碎片及在不同的时间中分配大尺寸对象的应用程序中。
• Concurrent collector (-XX:+UseConcMarkSweepGC):它使用一个单个的GC线程,和应用程序并行地执行大部分工作,它适合于具有快速处理器的机器和严格的服务水平协议的应用程序。它可能是最好的选择,也适用于使用大集合较长存活时间的HttpSessions的应用程序。
新的 G1收集器
在Java 7中主要增强的是新的G1(“垃圾至上”)低延迟的垃圾收集器,以计划取代在Hotspot JVM中的CMS,它是一种服务器式收集器,针对多处理器机器并使用大量的内存。
G1的收集是从早期的在新生代和年老代之间具有物理隔离的收集器分离而来的。G1收集器,即使它有代之分,但是两个代之间没有物理隔离。 这个收集器将整个空间划分为多个区间,允许一组区间被收集,而不是在空间中分割成绝对的新生代和年老代。
G1收集器的关键特性是:
1. G1采用当今硬件广泛使用的并行( parallelism),G1的主要优点是设计了这样一种方式,使用所有可用的CPU和利用所有CPU的处理能力,以此提高性能并加快垃圾收集速度。
2. 另外一个特性是它区别对待年轻的对象(新建)和年老对象(存活了一段时间),这在提升垃圾收集方面起了关键作用。G1主要关注在年轻的对象,他们通过变成年老对象可回收空间。
3. 堆压缩( Heap compaction)是为了消除碎片问题。从本质上说,是因为G1在处理时进行压缩,它会从堆中的一个区间拷贝对象到另一个区间。由于压缩,它不会遇到CMS的碎片问题。这样可能总能是从连续的可用空间中进行分配,使G1随着时间的推移具有一致的停顿时间。
相较于CMS,G1的收集器也更容易使用,因为它开关的数量较少,因此调整虚拟机更简单。G1已经在JDK 7中提供,现在人们可以尝试使用它。要使用G1,需要传递这两个开关参数:
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC
使用大内存页
在JVM的调优的另一个领域,应用程序通过使用大内存页可产生可观的提升。大内存页是现代CPU的一个特性,允许需要大内存的应用程序,以2-4 MB的块分配内存,而不是标准的4KB。从Java SE5.0开始,有一个跨平台的标志,需要大内存页设置:-XX:+ UseLargePages(在默认情况下Solaris是打开状态,Windows和Linux是关闭状态)。
大页面支持的目标是优化处理器转换后备缓冲器(TLB)。一个转换后备缓冲器是一个页面转换缓存,保存了最近使用的虚拟到物理地址的转换。TLB是一种稀缺的系统资源,TLB丢失可能导致昂贵的处理器必须再从分层页表中读出,这可能需要访问多个存储器。通过使用较大的页面尺寸,单个TLB项可以代表大内存范围,这对TLB造成较小的压力,存储器敏感型应用程序可以具有更好的性能。
在64位的JVM中可以设置大内存页。(红帽企业版Linux的32位操作系统上可以分配大页面,但启动JVM时你会得到一个非法参数的错误)。Sun JVM和OpenJDK一样,使用大页面需要在命令行上传递以下选项: -XX:+UseLargePages。
应用程序资源池
应用服务器池提供了几个好处,比如:
• 改善性能: 您可以重新分配资源敏感型的对象,如数据库连接,而不是每一次使用都创建和销毁它们。
• 加强安全: 通过授予有限的资源数量,可以防止服务器资源被应用程序过度使用从而可能导致服务的中断。
JBoss应用服务器AS7使用多个资源池来管理不同种类的服务。应用服务器附带的所有资源池的默认配置可能仅仅适用于简单应用程序,如果是关键型的应用程序,你需要恰当地配置资源池。
我们将在下个章节特别对在性能调优方面发挥重要作用的下列池进行讨论:
• 数据库连接池
• 无状态EJB使用的EJB池及 MDB
• Web服务器线程池
在撰写本文时,应用程序服务器并没有展示出这里我们提到的所有子系统(subsystem)的性能指标。尽管如此,通过管理界面来监控应用程序服务器池仍然是最佳方法,你仍然可以使用其他一些工具或以最小的示例应用程序来观察应用服务器池。这就是我们将在下节要讲的内容。(一旦性能调整指标可用,我们将及时更新这篇文章!)