您可能需要定制 Linux 系统,以提高服务器的性能。 下面,将向您介绍调整配置的技巧。 请牢记,这些系统可能会变化,从而导致这些建议过时,并导致您的结果有所不同。
在您为改善性能而进行任何更改之前,请确保已经对当前性能进行了度量。不管您是否关心事务执行速度、响应时间、最大并发用户数或其他一些性能条件,都需要在更改前后,进行足够准确地度量,以了解更改调优参数是否有效。
timeout_timewait 参数
timeout_timewait 值确定了在 TCP/IP 可释放已关闭的连接并复用其资源之前,必须等待的时间。 关闭和释放之间的时间间隔称为 TIME_WAIT 状态或最长分段生命周期的两倍(2MSL)状态。 在此期间,重新打开客户机和服务器之间的连接比新建一个连接的开销要小。 通过减小该项的值,TCP/IP 可更快地释放已关闭的连接,并可为新连接提供更多的资源。 如果由于多个连接处于 TIME_WAIT 状态导致吞吐量较低,从而正在运行的应用程序需要快速释放连接、创建新的连接或是进行调整,请调整这个参数。
缺省值是 240 秒(4 分钟)。
最小推荐值是 30 秒。 请使用以下过程来查看或定制您的值。
echo X > /proc/sys/net/ipv4/tcp_fin_timeout
其中 X 由期望的秒数替换。
connection backlog
可能需要提高连接储备值,以应对大量突发入局连接请求的情况。 如果同时接收到大量连接请求,使用较大的值会提高受支持的暂挂连接的数量,从而可减少连接失败的数量。
请使用以下过程来查看或定制您的值。
echo X > /proc/sys/net/core/netdev_max_backlog
echo X > /proc/sys/net/core/somaxconn
其中 X 大于在预期的突发入局请求中出现的最大连接请求数。
tcp_keepalive_time
tcp_keepalive_time 值控制 TCP/IP 尝试验证空闲连接是否完好的频率。 如果这段时间内没有活动,则会发送保持活动信号。 如果网络工作正常,而且接收方是活动的,它就会响应。 如果需要对丢失接收方敏感,换句话说,需要更快地发现丢失了接收方,请考虑减小这个值。 如果长期不活动的空闲连接出现次数较多,而丢失接收方的情况出现较少,您可能会要提高该值以减少开销。
缺省情况下,如果空闲连接 7200 秒(2 小时)内没有活动,Linux 就发送保持活动的消息。 通常,1800 秒是首选值,从而一半的已关闭连接会在 30 分钟内被检测到。
请使用以下过程来查看或定制您的值。
echo X > /proc/sys/net/ipv4/tcp_keepalive_time
其中 X 由期望的秒数替换。
tcp_keepalive_intvl 值
tcp_keepalive_intvl 值定义了如果未从接收方收到保持活动消息的响应,TCP/IP 重复发送保持活动信号的频率。 当连续发送保持活动信号、但未收到响应的次数超出 tcp_keepalive_probes 的值时,会放弃该连接。 如果期望较长的响应时间,您可能需要提高该值以减少开销。 如果需要减少花在验证接收方是否已丢失上的时间,请考虑减小该值或 tcp_keepalive_probes 值。
缺省情况下,在未收到响应而重新发送保持活动的消息之前,Linux 会等待 75 秒。 通常,15 秒是首选值,以便能够较快地检测到丢失了接收方。
请使用以下过程来查看或定制您的值。
echo X > /proc/sys/net/ipv4/tcp_keepalive_intvl
其中 X 由期望的秒数替换。
tcp_keepalive_probes 值
tcp_keepalive_probes 值定义了 TCP/IP 通过现有连接重新发送未返回应答的保持活动的消息次数。 如果您的网络性能很差,可能需要提高该值以保持有效的通信。 如果您的网络性能很好,可以减小该值以减少验证接收方是否丢失所花费的时间。
缺省情况下,在决定放弃该连接之前,Linux 会发送 9 次未返回应答的保持活动的消息。 通常,5 次是首选值,以便能够较快地检测到丢失了接收方。
请使用以下过程来查看或定制您的值。
echo X > /proc/sys/net/ipv4/tcp_keepalive_probes
其中 X 由在未返回应答的情况下,期望的用于保持活动的重新传输的次数替换。
大页面支持
使用大页面支持来管理虚拟存储器可降低管理 JAVA 虚拟机中大型堆所产生的 CPU 开销。 要使用这种支持,您必须配置系统以支持大页面,并在启动虚拟机时指定 -Xlp JVM 选项。
启用大页面支持的步骤取决于您使用的 Linux 分发版。 通常,您将编辑 sysctl.conf 文件并
- 设置保存最大 Java 堆所需的大页面的数量
- 设置用于保存最大 Java 堆的最大共享分段的大小
- 设置用于保存最大 Java 堆的共享内存的总数
然后将程序重新定位到一个较低的虚拟内存地址,以为较大的堆提供更多的地址空间。
WebSphere 调优
优化Web应用的性能绝不象有些人想象的那样简单易行,它涉及到诸多技术,从最简单的HTML代码修改,到复杂的EJB改造,无不涉及性能问题。但有一点是非常清楚的:要想找出和解决Web应用的性能瓶颈,就必须深入全面地了解信息在Web应用中的流程。
改善Web应用的性能不一定要局限于Web应用的Java代码,例如有些时候,简单地改动一下HTML页面的质量、减少其传输频度和数据量就可以有效地 提高应用的性能表现;有时提高性能的关键却在于修改Web应用的数据库访问部分――这只是Java代码之外影响性能的两个因素,其他还有许多因素会影响到 Web应用的整体性能表现。另一方面,就Java程序本身而言,其性能优化又可以分成三个领域:基本的Java代码优化,JSP/Servlet优化, EJB优化。
一、表现层优化
Web应用的最大性能瓶 颈常常不在其他地方,而在于最基本的网络带宽限制。如果你的Web应用也面临这类问题,提高性能最简单的办法是减少HTTP传输,例如用 JavaScript实现客户端编辑功能以减少数据传输次数,避免将数据发送到服务器端再执行合法性验证之类的编辑操作。
应当采用一切可能措施减少通过网络传输的数据。例如,你可以要求浏览器缓冲模块化的JavaScript文件,在SCRIPT标记的SRC中指定:
SCRIPT LANGUAGE="JavaScript" SRC="FormChek.js"。
其他减少网络传输应当注意的地方还包括:避免过度使用隐藏域,减少超长Cookie值,在RADIO、CHECKBOX和SELECT域中用代码来替代 长长的字符串,等等。不过在HTML优化方面本文不准备作全面的讨论,因为WebSphere应用的开发者一般不会担负设计表现层的责任,只要了解下面这 个原理就足够了:
性能技巧之一:尽可能减少HTTP数据传输的总量和频度
二、数据库访问
朋友小A对Java的了解极为有限,但他却成功地改进了许多WebSphere应用的性能。他是怎么做到的呢?原来,小A是一个数据库专家,他通过优化 数据库访问有效地改进了整个应用的性能,但对于Java,他只是略微了解一些有关JDBC的知识。在优化数据库访问时,小A做的第一件事情总是检查数据库 的设计,有时他会建议重新构造数据库的结构(必须指出的是,为了提高性能而重新构造数据库结构有时可能使数据库反规格化(De- Normalization),从而带来维护方面的问题)。
性能技巧之二:规格化(Normalization)数据库结构
小A做的第二件事情是执行数据库分析,根据分析结果提出增加某个索引、减少某个索引的建议。完成这一步骤后,小A通常可以让应用有令人满意的性能表现,根本不必去查看应用的Java代码。
性能技巧之三:针对常用的SQL操作建立索引,删除多余的索引
有时,为了进一步优化应用的性能,小A会检查Java(也许应该说是SQL)代码,经常找到Java程序没有合理运用 PreparedStatement和连接缓冲池的情形。只要把Statement类的动态SQL替换成PreparedStatement类的静态 SQL,从连接池提取SQL连接(而不是直接创建连接),应用的性能将得到显著的改善。注意DB2 UDB(包括其他一些数据库)的PreparedStatement是可调整和配置的。
性能技巧之四:合理运用PreparedStatement和连接池
进一步分析应用的工作流程之后,小A有时会建议批量执行某些SQL命令,这样就只需一个对数据库服务器的请求就可以运行大量的SQL命令。
性能技巧之五:考虑批量执行SQL命令
既然如此,小A有时还会指出,如果应用中有些SQL命令可以组合成单个事务逻辑,那么应该可以用一个存储过程来替代。DB2 UDB的存储过程语言(SPL,Stored Procedure Language)非常强大,如果把数据库操作逻辑从Web应用转移到数据库,一般总是对性能有益。不过需要注意的是,虽然批量执行SQL命令或使用存储 过程会提高性能,但就象重新构造数据库结构一样,有时会带来维护方面的困难。
性能技巧之六:考虑使用数据库存储过程
检查JDBC代码的时候,小A总是留意对象有没有及时正确释放。这一点其实很重要。
性能技巧之七:及时关闭不用的Statement、ResultSet、Connection等对象(但不是在finalize方法内)
三、Java代码
前面我们以小A的经验为例,探讨了Web应用中数据库访问性能的重要性。调整好数据库之后,接下来要做的自然是深入分析应用的Java代码。从哪里入手 呢?你最好使用Java分析工具来找出性能问题的焦点所在。优化Java代码的性能是一个艰苦的过程,因此一个重要的原则是把精力集中到那些可能引起性能 问题的代码上。换句话说,就是要尊重80/20规则:利用Java分析工具的结果,调整带来80%性能开销的那20%代码。
性能技巧之八:用Java分析工具清楚地界定性能问题所在
目前市场上已经有许多优秀的Java分析工具,例如ej-technologie的JProfile(http://www.ej- technologies.com),Klgroup的Jprobe(http://www.klg.com),以及Intuitive Systems的OptimizeIt(http://www.optimizeit.com)。不过不要忘记WebSphere Studio Application Developer(WSAD)本身也集成了一个优秀的分析器,有条件的话,最好多用几种分析工具分析Java代码。
考虑到资金问题,你不一定乐意购买昂贵的分析软件,但你可以用Java本身的命令行工具生成分析信息。例如,在JDK 1.3中,你可以用下面的命令将TestOrderProcessing类的CPU使用情况保存到java.hprof文件:java -Xrunhprof:cpu=times,format=a,file=java.hprof TestOrderProcessing。
这种办法的缺点是它提供的信息条理不够清楚,比较繁杂;也许可以找到一些源代码开放的工具辅助分析,但一般不如使用WSAD本身的分析工具或商业化的分析工具方便。另外,如果你已经了解哪些代码块可能引起性能问题,可以通过保存系统时间的方式获得分析信息,例如:
long startTime = System.currentTimeMillis();
// 执行某些操作
long endTime = System.currentTimeMillis();
3.1 基本篇
有人建议“稳定性第一,速度第二”,一般而言遵从这个建议是不会错的,但这并不妨碍我们在编写代码的同时运用某些已经证实的性能技巧。例如,我们都知道String类是不可变的,连接两个String是一项开销很大操作。
性能技巧之九:用StringBuffer来连接两个字符串
也许你已经注意到,Sun的许多标准Java类是线程安全的,这些类内部的同步机制实际上很容易造成性能问题。例如,Vector类就是一个线程安全的 类,除非确实要用到同步机制,否则使用Vector是不值得的,如有可能,应当尽量改用非线程安全的类如ArrayList。
性能技巧之十:只有在必要时才运用线程安全的类
许多人习惯使用System.out.println来输出跟踪信息,但println要占用不少资源,所以输出跟踪信息最好使用专用日志记录框架,如IBM的JRas或Apache的Log4j。
性能技巧之十一:用日志记录框架类输出跟踪信息,而不是使用System.out.println
最后一个提高代码性能的简单技巧是清除类里面的调试信息,减小类的体积。IBM有一个WSAD插件,它提供了一个叫做setDebugInfo的任务,可以从Ant脚本调用。
性能技巧之十二:从正式发行的软件中删除调试信息