JEE 应用服务器性能优化指南(基础篇)

 

中创软件 InforSuite JEE 应用服务器性能优化指南

链接地址:http://www.inforbus.com/xwzx/jswz/253907.shtml

1.1.   关于性能的一般讨论

1.1.1.   请求响应的主要过程

首先我们看一下在多用户情况一个 Web 程序从请求到响应的一个大致的过程。如 1


1 程序访问的主要过程

1 可知,总用户数 >> 在线用户数 >>CPU 正在处理的用户数 >> 正在进行数据库访问的用户数。按照 10 1 的概率估算,大约为 1000 总用户数, 100 在线用户数, 10 个正在处理用户数, 1 个数据库访问用户数。当然这个估算值没有实际意义,但是可以帮助我们建立起在多用户情况下系统运行的一个概貌。

1.1.2.   性能优化要素

1.1.2.1.   硬件因素

硬件对系统性能有着至关重要的影响。具体来看,直接影响系统性能的硬件指标包括:

l         CPU CPU 完成业务逻辑的计算,因此提供足够的 CPU 时间对性能有着重要的影响。尤其在出现性能瓶颈时,如果 CPU 仍然处于闲置状态,则我们需要检查为何导致了 CPU 的空转等待。如果 CPU 已经使用 100% ,则我们需要检查此刻 CPU 处理的业务逻辑是否是必须的,或者可优化的。

l         内存:内存为程序运行提供了物理空间。对 Java 程序来说,不但需要关注物理内存的设置,还必须关注 JVM 内存的设置。在出现性能瓶颈时,观察整个物理内存和 JVM 内存的使用情况,将有助于我们指定合适的内存分配策略。关于 JVM 内存的设置情况我们将在后面展开论述。

l         网络:服务器与客户端的数据通过网络进行传输,因此网络传输能力也是影响性能的一个关键指标。可以通过 Tracert/ping 命令来跟踪系统的网络环境。如果通过专门的网络带宽测试工具进行带宽检测,将更有助于问题的分析。

l         I/O I/O 对系统性能的影响最大的后果就是会形成 CPU 的无效等待。即虽然系统运行很慢,但是可能 CPU 使用率仍然很低,这是可能存在的瓶颈就在于 I/O 尚未完成, CPU 处于空闲等待状态。采用内存缓存、聚簇索引以及 RAID 技术都能够有效提高 I/O 的效率。

1.1.2.2.   软件因素

2 性能优化的软件因素

在给定硬件条件下,要达到性能的提升,目标无非就是用最短的路径(最精简的业务逻辑)、最快的速度(减少等待,增大系统吞吐量)执行完所需的程序。最短路径这个因素是由程序的逻辑算法决定的。一个程序写完后,所需的路径也就确定了下来。最快速度这个因素是由程序执行各个环节的参数配置决定的。通过了解程序访问的主要过程,我们已经了解到哪些参数会对执行速度有比较大的影响。

总起来看性能优化的主要思路为:

l         优化程序的逻辑算法,减少不必要的程序逻辑,尽量形成一个最短的程序执行路径。比如利用高级排序算法代替普通排序算法。

l         调整影响程序执行速度的参数,减少不必要的等待,尽量增加系统的吞吐量( throughput ),比如通过调整 Web 连接器数、 Web 线程池的线程数以及数据源线程池的线程数,来加快多用户请求的处理速度。既然是参数调整就必然没有统一的答案,而是一个根据实际情况不断反复对比试验的过程。性能调优在英文中翻译为“ Performance Tuning ”也极具神采。

在本文中,针对性能优化的讨论主要侧重于调整影响程序速度的参数上,对于优化程序的逻辑算法并不涉及。

1.2.   JVM 配置参数

系统 JVM 的配置和系统的性能有着比较大的关系,特别当系统的处理能力成某种变化趋势时,要考虑到系统 GC 对系统性能的影响,为了找到两者的关系,可以通过采样,图形比较来进行分析。如果发现二者之间有密切的联系,可以考虑对 JVM 的配置进行优化,比如:对最优化堆的大小进行调整。

If the garbage collector has become a bottleneck, you may wish to customize the generation sizes. Check the verbose garbage collector output, and then explore the sensitivity of your individual performance metric to the garbage collector parameters

——摘自 http://java.sun.com/docs/hotspot/gc1.4.2/

1.2.1.   最大堆大小设置原则

对于不同的应用程序,最优化堆大小的设置都有可能不同。如果堆设置较大,可能导致 GC 的次数变少,但每次 GC 所花的时间很长,从而导致系统的处理能力抖动很大。此外如果堆设置过大,会占用过多的内存,使内存资源耗尽,从而会频繁的进行 IO 操作来使用虚拟内存。 如果堆设置较小,可能导致 GC 变的频繁,但每次 GC 所花的时间不会太长,每次 GC 对系统的性能影响相对也会小些。但是如果堆设置过小, 会使得对象可分配空间变小,从而会频繁的 GC 来释放内存空间,而每次 GC ,都会耗用一定的系统资源。因此,要通过试验和监控数据,设法使的我们所设置的堆大小能够使得系统运行最优化。

由于 JVM 实现机制不一样,所以针对不同厂商的虚拟机,以及同一厂商不同虚拟机的版本, Java 堆参数的配置也不尽相同。

1.2.1.1.   针对 Sun 的虚拟机

对于 Sun JVM 来说,它的 GC 策略默认是复制、分代算法。也就是说,它会将 heap 分成不同的几个区,譬如 Solaris JVM 中最上面有两个大小相等的区。 GC 时刻,将一个区的存活对象复制到另外一个对等区,垃圾对象就算遗弃了。这样在 heap 里面,就不存在碎片问题。另外 Sun JVM 有单独的方法区,也就是 Permanent Generation ,方法区中保存的一般是 Class 对象,而不是普通的实例对象,也就是 JVM 的元数据。

因此通常情况下,对于 Sun 的虚拟机只需要配置 heap 最大最小值,以及 maxPermSize 就可以了。

1.2.1.1.1. 配置 heap 最小最大值

对于 Sun JVM 来说,一般可以设置 heap 最大最小值一致,也是推荐的做法。因为它的 GC 策略默认是复制、分代算法。也就是说,它会将 heap 分成不同的几个区,譬如 Solaris JVM 中最上面有两个大小相等的区。 GC 时刻,将一个区的存活对象复制到另外一个对等区,垃圾对象就算遗弃了。这样在 heap 里面,就不存在碎片问题。另外,根据 Java 对象的存活期不同,将之转移到不同的区( Tenured 区),存活最长的在最底部(火车算法),这也就是分代模型。具体请参考官方文档: http://java.sun.com/docs/hotspot/gc1.4.2/

Unless you have problems with pauses, try granting as much memory as possible to the virtual machine. The default size (64MB) is often too small.

Setting -Xms and -Xmx to the same value increases predictability by removing the most important sizing decision from the virtual machine. On the other hand, the virtual machine can't compensate if you make a poor choice.

Be sure to increase the memory as you increase the number of processors, since allocation can be parallelized.

1.2.1.1.2. 关于 maxPermSize Permanent Generation

对于 maxPermSize Permanent Generation ),主要和那些加载到 JVM 里面的 Java Class 对象相关,它的空间不是在 Java Heap 里面分配。如果你当前的 heap 1000M permSize 200M ,那么 JVM 至少占用 1200M

在这个空间内的对象的生存期和 JVM 是一样的,譬如 JDK 的核心类库,它们被 System Classloader 加载到 JVM Method Area (方法区)后,就不会被 GC 掉的,这些对象一般是 Class 对象,而不是普通的实例对象,也就是 JVM 的元数据。我们在用反射时经常用到它们。所以,对于现在象 Spring Hibernate 这些框架经常通过反射创建实例,可能对 maxPermSize 要求就大了,缺省的 64M 很多时候是不够的,特别是对于应用服务器里的应用,象 JSP 就会产生和加载很多 classes 。不过,如果是它导致的 OOM ,一般会有类似 perm size 提示。

1.2.1.2.   针对 IBM 的虚拟机

IBM JVM 默认 GC 策略并没有采取复制、分代。这个可以从 GC 日志分析出来。它不像 Sun JVM 那样,有个单独的方法区,它的方法区就放在 Java Heap 里面。在 IBM JVM 里面,这些对象一般分配在称为 k-cluster p-cluster 里( cluster 又是属于 Heap ),而后者一般是临时在 heap 里面申请。并且,这些 cluster 是不能 GC ,或是被移动重排的( Compact 过程)。这就导致 Java Heap 里面就如同蜂窝,但不同的蜂孔又不能合并,于是,当我们程序里面产生一个大对象,譬如 2M 的数组 ( 数组必须分配在连续的内存区 ) 时,就没有可分配空间了,于是就报告 OOM 。这些不能被移动的 cluster 之间的空隙就称为所谓的碎片。此时, JVM Heap 利用率可能不到 50%

针对 IBM JDK 1.4.2 的内存碎片问题的解决,总结如下:

1.         初始堆大小要小于 256MB 和最大堆大小的 1/4 2 个值中小的那个。

2.         调整 JVM K 簇和 P 簇的值

IBM JDK 1.5 已经重新写了 JVM 。据说 GC 算法改了,碎片问题应该会好很多。

1.2.2.   JVM 查看

InforSuite 管理平台提供了详细的 JVM 查看功能,登陆管理平台后,在“监控”下的“系统信息”菜单下能够动态检测内存的使用情况。如 3


3 JVM 查看

另外, InforSuite 管理平台提供了动态的内存监控工具,用户也可以通过该工具进行内存监控。

1.2.3.   JVM 内存调整

InforSuite5.1 版本使用了 Sun 的虚拟机,因此遵循 Sun 公司虚拟机的修改方式。通过修改 inforsuite.bat 脚本可以实现对 JVM 内存的调整。调整参数中比较重要的几个为:

initial heap size:

Larger of 1/64th of the machine's physical memory on the machine or some reasonable minimum. Before J2SE 5.0, the default initial heap size was a reasonable minimum, which varies by platform. You can override this default using the -Xms command-line option.

maximum heap size:

Smaller of 1/4th of the physical memory or 1GB. Before J2SE 5.0, the default maximum heap size was 64MB. You can override this default using the -Xmx command-line option.

-XX:MaxPermSize

  Size of the Permanent Generation.  [5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.]

比如在 inforsuite.bat 增加如下语句 可以实现对 JVM 初始堆、最大堆以及永久代的设置

  set JAVA_OPTS=%JAVA_OPTS%   -Xms64m -Xmx512m -XX:MaxPermSize=256m

1.3.   Web 连接器

InforSuite Web 连接器和 Web 线程池的大小均通过 Web 连接器的属性进行配置。默认状态下 InforSuite V5.1 版本提供了 4 个连接器。对于使用 HtttP 协议和 HttPS 协议进行通讯的普通 Web 应用来说,只需配置对应的 HTTPConnector HTTPSConnector 就可以了。

InforSuite 管理平台的“监控”菜单下的“线程池”目录下,提供了对相应连接器的监控界面。通过控制面板的“监听器实时动态图”能够动态检测 Web 线程池的运行情况。更多的监听器运行指标可以通过“监听器状态”获得。

根据系统实际情况来调整 Web 连接器和 Web 线程池的大小。调整方法为:

l         调整 WEB 线程池大小:对应到连接器的“最大线程数”属性。该属性决定了 CPU 能够同时处理在线用户请求的最大能力。

l         调整 Web 连接器大小:对应到连接器的“接受数”属性。该属性决定了 Web 线程池都被占用时,允许接收连接请求队列的最大长度。因此调整该值能够增大系统的在线用户支持能力。

1.4.   数据库连接池

数据库连接池技术已经非常成熟,对于优化数据库访问和数据库资源的合理利用具有关键作用。 InforSuite 提供了具有良好性能和稳定性的数据库连接池。数据库连接池的性能调整参数主要是连接池最大容量、最小容量以及最大阻塞超时和最大空闲超时时间。调整方法如 4


4 数据库连接池参数调整

另外,数据库连接的释放问题经常成为项目开发中的一个陷阱,因为各种工具都提供了自己的数据库连接池技术,但是每个连接池的资源释放策略各有不同。这就可能导致项目组成员采用了不恰当的资源释放方式。为了避免该类问题的发生,应该尽量使用一种数据库连接池方式,从而统一使用方法(推荐使用应用服务器 InforSuite 的连接池,这样将便与监控与管理)。

1.5.   数据库优化

当应用服务器处于空闲等待状态,而数据库服务器迟迟无法返回结果时,这一般就意味着要对数据库性能展开优化了。数据库性能优化和应用服务器性能优化相比,本身是就一个博大的话题。因此本文并不针对数据库性能优化展开论述。仅就查询来说大致参数包括:

数据分区:数据在存储时就进行处理,可增大 I/O ,提高查询速度

聚簇索引:建立索引,快速查找

SQL 优化:减少查询复杂度

统计信息收集:通过数据库自带的统计信息收集工具能够提高查询性能

降低日志记录开销:减少 I/O ,减少日志缓冲区。

 

你可能感兴趣的:(JEE 应用服务器性能优化指南(基础篇))