`

Tomcat性能调优(2)

阅读更多
四. 自身调整

  本节将向您详细介绍一些加速可使Tomcat实例加速运行的技巧和方法,无论是在什么操作系统或者何种Java虚拟机上。在有些情况下,您可能没有控制部署环境上的操作系统或者Java虚拟机。在这种情况下,您就需要逐行了解以下的的一些建议,然而你应该在修改后使之生效。我认为以下方法是Tomcat性能自身调整的最佳方式。

  1.禁用DNS查询

  当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名转换为IP地址。DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。为了消除DNS查询对性能的影响我们可以关闭DNS查询,方式是修改server.xml文件中的enableLookups参数值:

Tomcat4

<Connector className="org.apache.coyote.tomcat4.CoyoteConnector" port="80" minProcessors="5" maxProcessors="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" useURIValidationHack="false" disableUploadTimeout="true" />

Tomcat5

<Connector port="80" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true"/>


  除非你需要连接到站点的每个HTTP客户端的机器名,否则我们建议在生产环境上关闭DNS查询功能。可以通过Tomcat以外的方式来获取机器名。这样不仅节省了网络带宽、查询时间和内存,而且更小的流量会使日志数据也会变得更少,显而易见也节省了硬盘空间。对流量较小的站点来说禁用DNS查询可能没有大流量站点的效果明显,但是此举仍不失为一良策。谁又见到一个低流量的网站一夜之间就流量大增呢?

  2.调整线程数

  另外一个可通过应用程序的连接器(Connector)进行性能控制的的参数是创建的处理请求的线程数。Tomcat使用线程池加速响应速度来处理请求。在Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。

  Tomcat4中可以通过修改minProcessors和maxProcessors的值来控制线程数。这些值在安装后就已经设定为默认值并且是足够使用的,但是随着站点的扩容而改大这些值。minProcessors服务器启动时创建的处理请求的线程数应该足够处理一个小量的负载。也就是说,如果一天内每秒仅发生5次单击事件,并且每个请求任务处理需要1秒钟,那么预先设置线程数为5就足够了。但在你的站点访问量较大时就需要设置更大的线程数,指定为参数maxProcessors的值。maxProcessors的值也是有上限的,应防止流量不可控制(或者恶意的服务攻击),从而导致超出了虚拟机使用内存的大小。如果要加大并发连接数,应同时加大这两个参数。web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。

  在Tomcat5对这些参数进行了调整,请看下表:
属性名
描述

maxThreads
Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数。

acceptCount
指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。

connnectionTimeout
网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。

minSpareThreads
Tomcat初始化时创建的线程数。

maxSpareThreads
一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。



  最好的方式是多设置几次并且进行测试,观察响应时间和内存使用情况。在不同的机器、操作系统或虚拟机组合的情况下可能会不同,而且并不是所有人的web站点的流量都是一样的,因此没有一刀切的方案来确定线程数的值。

  3.加速JSP编译速度

  当第一次访问一个JSP文件时,它会被转换为Java serverlet源码,接着被编译成Java字节码。你可以控制使用哪个编译器,默认情况下,Tomcat使用使用命令行javac进行使用的编译器。也可以使用更快的编译器,但是这里我们将介绍如何优化它们。

  另外一种方法是不要把所有的实现都使用JSP页面,而是使用一些不同的java模板引擎变量。显然这是一个跨越很大的决定,但是事实证明至少这种方法是只得研究的。如果你想了解更多有关在Tomcat可使用的模板语言,你可以参考Jason Hunter和William Crawford合著的《Java Servlet Programming 》一书(O"Reilly公司出版)。

  在Tomcat 4.0中可以使用流行而且免费的Jikes编译器。Jikes编译器的速度要由于Sun的Java编译器。首先要安装Jikes(可访问http://oss.software.ibm.com/pub/jikes 获得更多的信息),接着需要在环境变量中设置JIKESPATH包含系统运行时所需的JAR文件。装好Jikes以后还需要设置让JSP编译servlet使用Jikes,需要修改web.xml文件中jspCompilerPlugin的值:


<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>jspCompilerPlugin</param-name>
<param-value>
org.apache.jasper.compiler.JikesJavaCompiler
</param-value>
</init-param>
<init-param>
<!-- <param-name>
org.apache.catalina.jsp_classpath
</param-name> -->
<param-name>classpath</param-name>
<param-value>
/usr/local/jdk1.3.1-linux/jre/lib/rt.jar:
/usr/local/lib/java/servletapi/servlet.ja
r</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>


  在Tomcat 4.1(或更高版本),JSP的编译由包含在Tomcat里面的Ant程序控制器直接执行。这听起来有一点点奇怪,但这正是Ant有意为之的一部分,有一个API文档指导开发者在没有启动一个新的JVM的情况下,使用Ant。这是使用Ant进行Java开发的一大优势。另外,这也意味着你现在能够在Ant中使用任何javac支持的编译方式,这里有一个关于Apache Ant使用手册的javac page列表。使用起来是容易的,因为你只需要在 元素中定义一个名字叫“compiler”,并且在value中有一个支持编译的编译器名字,示例如下:


<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>
org.apache.jasper.servlet.JspServlet
</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>compiler</param-name>
<param-value>jikes</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>



Ant可用的编译器
名称
别名
调用的编译器

classic
javac1.1, javac1.2
Standard JDK 1.1/1.2 compiler

modern
javac1.3, javac1.4
Standard JDK 1.3/1.4 compiler

jikes
   The Jikes compiler

JVC Microsoft
Microsoft command-line compiler from the Microsoft SDK for Java/Visual J++

KJC    The kopi compiler

GCJ    The gcj compiler (included as part of gcc)

SJ Symantec
Symantec"s Java compiler

extJavac
   Runs either the modern or classic compiler in a JVM of its own



  由于JSP页面在第一次使用时已经被编译,那么你可能希望在更新新的jsp页面后马上对它进行编译。实际上,这个过程完全可以自动化,因为可以确认的是新的JSP页面在生产服务器和在测试服务器上的运行效果是一样的。

  在Tomcat4的bin目录下有一个名为jspc的脚本。它仅仅是运行翻译阶段,而不是编译阶段,使用它可以在当前目录生成Java源文件。它是调试JSP页面的一种有力的手段。

  可以通过浏览器访问再确认一下编译的结果。这样就确保了文件被转换成serverlet,被编译了可直接执行。这样也准确地模仿了真实用户访问JSP页面,可以看到给用户提供的功能。也抓紧这最后一刻修改出现的bug并且修改它J

  Tomcat提供了一种通过请求来编译JSP页面的功能。例如,你可以在浏览器地址栏中输入http://localhost:8080/examples/jsp/dates/date.jsp?jsp_precompile=true,这样Tomcat就会编译data.jsp而不是执行它。此举唾手可得,不失为一种检验页面正确性的捷径。

  4. 其它

  前面我们提到过操作系统通过一些限制手段来防止恶意的服务攻击,同样Tomcat也提供了防止恶意攻击或禁止某些机器访问的设置。

  Tomcat提供了两个参数供你配置:RemoteHostValve 和RemoteAddrValve。

  通过配置这两个参数,可以让你过滤来自请求的主机或IP地址,并允许或拒绝哪些主机/IP。与之类似的,在Apache的httpd文件里有对每个目录的允许/拒绝指定。

  例如你可以把Admin Web application设置成只允许本地访问,设置如下:


<Context path="/path/to/secret_files" ...>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"

allow="127.0.0.1" deny=""/>
</Context>


  如果没有给出允许主机的指定,那么与拒绝主机匹配的主机就会被拒绝,除此之外的都是允许的。与之类似,如果没有给出拒绝主机的指定,那么与允许主机匹配的主机就会被允许,除此之外的都是拒绝的。


五. 容量计划

  容量计划是在生产环境中使用Tomcat不得不提的提高性能的另一个重要的话题。如果你没有对预期的网络流量下的硬件和带宽做考虑的话那么无论你如何做配置修改和测试都无济于事。

  这里先对提及的容量计划作一个简要的定义:容量计划是指评估硬件、操作系统和网络带宽,确定应用服务的服务范围,寻求适合需求和软件特性的软硬件的一项活动。因此这里所说的软件不仅包括Tomcat,也包括与Tomcat结合使用的任何第三方web服务器软件。

  如果在购买软硬件或部署系统前你对容量计划一无所知,不知道现有的软硬件环境能够支撑多少的访问量,甚至更糟直到你已经交付并且在生产环境上部署产品后才意识到配置有问题时再进行变更可能为时已晚。此时只能增加硬件投入,增加硬盘容量甚至购买更好的服务器。如果事先做了容量计划那么就不会搞的如此焦头烂额了。

  我们这里只介绍与Tomcat相关的内容。

  首先为了确定Tomcat使用机器的容量计划,你应该从一下列表项目种着手研究和计划:

  1. 硬件

  采用什么样的硬件体系?需要多少台计算机?使用一个大型的,还是使用多台小型机?每个计算机上使用几个CPU?使用多少内存?使用什么样的存储设备,I/O的处理速度有什么要求?怎样维护这些计算机?不同的JVM在这些硬件上运行的效果如何(比如IBM AIX系统只能在其设计的硬件系统上运行)?

  2. 网络带宽

  带宽的使用极限是多少?web应用程序如何处理过多的请求?

  3. 服务端操作系统

  采用哪种操作系统作为站点服务器最好?在确定的操作系统上使用哪个JVM最好?例如,JVM在这种系统上是否支持本地多线程,对称多处理?哪种系统可使web服务器更快、更稳定,并且更便宜。是否支持多CPU?

  4. Tomcat容量计划

  以下介绍针对Tomcat做容量计划的步骤:

  1) 量化负载。如果站点已经建立并运行,可以使用前面介绍的工具模仿用户访问,确定资源的需求量。

  2) 针对测试结果或测试过程中进行分析。需要知道那些请求造成了负载过重或者使用过多的资源,并与其它请求做比较,这样就确定了系统的瓶颈所在。例如:如果servlet在查询数据库的步骤上耗用较长的时间,那么就需要考虑使用缓冲池来降低响应时间。

  3) 确定性能最低标准。例如,你不想让用户花20秒来等待结果页面的返回,也就是说甚至在达到访问量的极限时,用户等待的时间也不能超过20秒种(从点击链接到看到返第一条返回数据)。这个时间中包含了数据库查询时间和文件访问时间。同类产品性能在不同的公司可能有不同的标准,一般最好采取同行中的最低标准或对这个标准做出评估。

  4) 确定如何合理使用底层资源,并逐一进行测试。底层资源包括CPU、内存、存储器、带宽、操作系统、JVM等等。在各种生产环境上都按顺序进行部署和测试,观察是否符合需求。在测试Tomcat时尽量多采用几种JVM,并且调整JVM使用内存和Tomcat线程池的大小进行测试。同时为了达到资源充分合理稳定地使用的效果,还需针对测试过程中出现的硬件系统瓶颈进行处理确定合理的资源配置。这个过程最为复杂,而且一般由于没有可参考的值所以只能靠理论推断和经验总结。

  5) 如果通过第4步的反复测试如果达到了最优的组合,就可以在相同的生产环境上部署产品了。

  此外应牢记一定要文档化你的测试过程和结果,因为此后可能还会进行测试,这样就可以拿以前的测试结果做为参考。另外测试过程要反复多次进行,每次的条件可能都不一样,因此只有记录下来才能进行结果比较和最佳条件的选择。

  这样我们通过测试找到了最好的组合方式,各种资源得到了合理的配置,系统的性能得到了极大的提升。


六. 附加资料

  很显然本文也很难全面而详尽地阐述性能优化过程。如果你进行更多研究的话可能会把性能调优做的更好,比如Java程序的性能调整、操作系统的调整、各种复杂环境与应用系统和其它所有与应用程序相关的东西。在这里提供一些文中提到的一些资源、文中提到的相关内容的链接以及本文的一些参考资料。

  1. Web性能测试资料及工具

  1) Jmeter Wiki首页,Jmeter为一个开源的100%Java开发的性能测试工具
  http://wiki.apache.org/jakarta-jmeter/

  2) Apache Benchmark使用说明
  http://httpd.apache.org/docs-2.0/programs/ab.html

  3) 一些Java相关测试工具的介绍,包含可以与Tomcat集成进行测试的工具
  http://blog.csdn.net/wyingquan/

  4) LoadRunner® 是一种预测系统行为和性能的工业标准级负载测试工具。它通过模拟数据以千万计用户来实施并发负载来对整个企业架构进行测试,来帮助您更快的查找和发现问题。
  http://www.mercury.com/us/products/performance-center/loadrunner/


  2. 文中介绍的相关内容的介绍

  1) Apache 2.x + Tomcat 4.x做负载均衡,描述了如何利用jk配置集群的负载均衡。
  http://raibledesigns.com/tomcat/index.html

  2) 容量计划的制定,收集了许多有关制定web站点容量计划的例子:
  http://www.capacityplanning.com/

  3) 评测Tomcat5负载平衡与集群,
  http://www.javaresearch.org/article/showarticle.jsp?column=556&thread=19777

  4) Apache与Tomcat的安装与整合之整合篇
  http://www.javaresearch.org/article/showarticle.jsp?column=23&thread=18139

  5) 性能测试工具之研究,介绍了性能测试工具的原理与思路
  http://www.51testing.com/emagzine/No2_2.htm

  6) Java的内存泄漏
  http://www.matrix.org.cn/resource/article/409.html

  7) Web服务器和应用程序服务器有什么区别?
  http://www.matrix.org.cn/resource/article/1429.html

  8) 详细讲解性能中数据库集群的问题
  http://www.theserverside.com/articles/article.tss?l=DB_Break

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics