首页 > 代码库 > Java应用Tomcat执行过程之性能调优

Java应用Tomcat执行过程之性能调优

     Java应用Tomcat执行过程之性能调优(整理两天时间、转载请注出处)


1、简介

     Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容器,按照Sun Microsystems提供的技术规范,实现了对ServletJavaServer PageJSP)的支持,并提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。
     Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。
     Tomcat和Nginx、Apache(httpd)、lighttpd等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Nginx/Apache服务器。


2、Tomcat的执行过程

技术分享

ps:画图好丑(画图工具画的,Do not worry);

请求过程描述:

      1、用户发送请求,被转发到8080端口,被Coyote Http/1.1 Connector获取。

      2、Connector把请求交给service的Engine来处理,并等待engine的回应。

            2.1、Engine获取到请求localhost/index.jsp,匹配所有的虚拟主机Host。

            2.2、Engine匹配到名localhost的Host,匹配它所有的Context。

            2.3、path=“/”的context获得请求/index.jsp,在它所拥有的mapping table中寻找对应的servlet。context匹配到URLPATHERN为*.jsp的servlet,对应的JSPServlet类。

            2.4、构造HttpServletRequest对象和HttpServletResponse对象。作为参数调用JspServlet的doGet()或者doPost()方法执行业务逻辑。

            2.5、Context把执行完的HttpServletRequest对象和HttpServletResponse对象返回给Host。

            2.6、Host把HttpServletResponse对象返回给Engine。

      3、Engine把HttpServletResponse对象返回给Connector。

      4、Connector把HttpServletResponse对象返回给客户。



 

2、目录结构与配置

2.1、目录结构

bin 存放启动和关闭tomcat脚本 
conf 包含不同的配置文件,server.xml(Tomcat的主要配置文件)和web.xml 
work 存放jsp编译后产生的class文件 
webapp 存放应用程序示例,以后你要部署的应用程序也要放到此目录 
logs 存放日志文件 
lib/japser/common 这三个目录主要存放tomcat所需的jar文件



2.2、Server.xml配置详解

  • 顶级组件:位于整个配置的顶层,如server。
  • 容器类组件:可以包含其它组件的组件,如service、engine、host、context。
  • 连接器组件:连接用户请求至tomcat,如connector。
  • 被嵌套类组件:位于一个容器当中,不能包含其他组件,如Valve、logger。

<server>
     <service>
     <connector/>
     <engine>
     <host>
     <context></context>
     </host>
     <host>
     <context></context>
     </host>
     </engine>
     </service>
</server>

 

2.3、组件详解

  • engine:核心容器组件,catalina引擎,负责通过connector接收用户请求,并处理请求,将请求转至对应的虚拟主机host。
  • host:类似于httpd中的虚拟主机,一般而言支持基于FQDN的虚拟主机。
  • context:定义一个应用程序,是一个最内层的容器类组件(不能再嵌套)。配置context的主要目的指定对应对的webapp的根目录,类似于httpd的alias,其还能为webapp指定额外的属性,如部署方式等。
  • connector:接收用户请求,类似于httpd的listen配置监听端口的。
  • service(服务):将connector关联至engine,因此一个service内部可以有多个connector,但只能有一个引擎engine。service内部有两个connector,一个engine。因此,一般情况下一个server内部只有一个service,一个service内部只有一个engine,但一个service内部可以有多个connector。
  • server:表示一个运行于JVM中的tomcat实例。
  • Valve:阀门,拦截请求并在将其转至对应的webapp前进行某种处理操作,可以用于任何容器中,比如记录日志(access log valve)、基于IP做访问控制(remote address filter valve)。
  • logger:日志记录器,用于记录组件内部的状态信息,可以用于除context外的任何容器中。
  • realm:可以用于任意容器类的组件中,关联一个用户认证库,实现认证和授权。可以关联的认证库有两种:UserDatabaseRealm、MemoryRealm和JDBCRealm。
  • UserDatabaseRealm:使用JNDI自定义的用户认证库。
  • MemoryRealm:认证信息定义在tomcat-users.xml中。
  • JDBCRealm:认证信息定义在数据库中,并通过JDBC连接至数据库中查找认证用户。


2.4、server.xml文件注释解析

<?xml version=‘1.0‘ encoding=‘utf-8‘?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 
-->
<!-- 
	 这会让Tomcat启动一个server实例(即一个JVM),它监听在8005端口以接收shutdown命令,
	 使用 telnet 连接8005 端口可以直接执行 SHUTDOWN 命令来关闭 Tomcat。各Server的定义
	 不能使用同一个端口,这意味着如果在同一个物理机上启动了多个Server实例,必须配置它
	 们使用不同的端口。这个端口的定义用于为管理员提供一个关闭此实例的便捷途径,因此,
	 管理员可以直接telnet至此端口使用SHUTDOWN命令关闭此实例。不过,基于安全角度的考虑,
	 这通常不允许远程进行。
 -->
<Server port="8005" shutdown="SHUTDOWN">
  <!--
	<Server>元素代表整个容器,是Tomcat实例的顶层元素.由org.apache.catalina.Server接口来定义.它包含
	一个<Service>元素.并且它不能做为任何元素的子元素.
    port指定Tomcat监听shutdown命令端口.终止服务器运行时,必须在Tomcat服务器所在的机器上发出
	shutdown命令.该属性是必须的.
    shutdown指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性必须设置
  -->
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
	<!--	 
	<Connector>连接器:Tomcat 连接器必须实现 org.apache.catalina.Connector 接口。
	在这个接口的众多方法中,最重要的是 getContainer,setContainer, createRequest 和 createResponse。

		setContainer 是用来关联连接器和容器用的 。 getContainer 返回关联的容器 。
		createRequest 为前来的 HTTP 请求构造一个请求对象,而 createResponse 创建一个响应对象。
				 
	 一般说来,常见于server.xml中的连接器类型通常有4种:
	1) HTTP连接器 
	2) SSL连接器 
	3) AJP 1.3连接器 
	4) proxy连接器

	定义连接器时可以配置的属性非常多,但通常定义HTTP连接器时必须定义的属性只有“port“,
	定义AJP连接器时必须定义的属性只有”protocol”,因为默认的协议为HTTP。以下为常用属性
	的说明:

    connector的属性:接收用户请求,类似于httpd的listen配置监听端口。
        port指定服务器端要创建的端口号,并在这个端口监听来自客户端的请求。
        address:指定连接器监听的地址,默认为所有地址(即0.0.0.0)。
        protocol连接器使用的协议,支持HTTP和AJP。AJP(Apache Jserv Protocol)专用于tomcat与apache建立通信的, 在httpd反向代理用户请求至tomcat时使用(可见Nginx反向代理时不可用AJP协议)。
        minProcessors服务器启动时创建的处理请求的线程数。
        maxProcessors最大可以创建的处理请求的线程数。
        enableLookups如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址。
        redirectPort指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号。
        acceptCount指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
        connectionTimeout指定超时的时间数(以毫秒为单位)。
	-->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
	<!--
	Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server核心容器组件,catalina引擎,
	负责通过connector接收用户请求,并处理请求,将请求转至对应的虚拟主机hostdefaultHost指定缺省的处
	理请求的主机名,它至少与其中的一个host元素的name属性值是一样的。
	
	Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。
	Engine需要defaultHost属性来为其定义一个接收所有发往非明确定义虚拟主机的请求的host组件。
	
	defaultHost:Tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在Engine容器中定义多个不同的
		Host组件来实现;但如果此引擎的连接器收到一个发往非非明确定义虚拟主机的请求时则需要将此请求发
		往一个默认的虚拟主机进行处理,因此,在Engine中定义的多个虚拟主机的主机名称中至少要有一个
		跟defaultHost定义的主机名称同名;
	name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎;
	Engine容器中可以包含Realm、Host、Listener和Valve子容器。
    -->
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
		<!--
		一个Realm表示一个安全上下文,它是一个授权访问某个给定Context的用户列表和某用户
		所允许切换的角色相关定义的列表。因此,Realm就像是一个用户和组相关的数据库。
		定义Realm时惟一必须要提供的属性是classname,它是Realm的多个不同实现,用于表示
		此Realm认证的用户及角色等认证信息的存放位置。
		-->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"  resourceName="UserDatabase"/>
      </Realm>
	  <!--
		位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机;
		1) appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;
			可以使用基于$CATALINA_HOME的相对路径;
		2) autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;
			默认为true;
		3) unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;
	  -->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
		<!--
        Context表示一个web应用程序,通常为WAR文件
            docBase应用程序的路径或者是WAR文件存放的路径,也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径。
            path表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/****
            reloadable这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,可以在不重启tomcat的情况下改变应用程序
        -->
		<Context path="" docBase="" debug=""/>
		
		<!--	 
		Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context
		和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它
		们生效的次序。Tomcat6中实现了多种不同的Valve:

		AccessLogValve:访问日志Valve
		ExtendedAccessValve:扩展功能的访问日志Valve
		JDBCAccessLogValve:通过JDBC将访问日志信息发送到数据库中;
		RequestDumperValve:请求转储Valve;
		RemoteAddrValve:基于远程地址的访问控制;
		RemoteHostValve:基于远程主机名称的访问控制;
		SemaphoreValve:用于控制Tomcat主机上任何容器上的并发访问数量;
		JvmRouteBinderValve:在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使JvmRouteSessionIDBinderListener;
		ReplicationValve:专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制;
		SingleSignOn:将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp;
		ClusterSingleSingOn:对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作;
			 -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>



3、Tomcat监控

        JConsole的图形用户界面是一个符合java管理扩展(JMX)规范的监测工具,JConsole使用java虚拟机(java VM),提供在Java平台上运行的应用程序的性能和资源消耗的信息。在jdk安装目录下的bin文件包下;

技术分享


4、Tomcat安全优化和性能优化

4.1、禁用DNS查询(enableLookups="false")

      当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名 转换为IP地址。DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。

      修改server.xml文件中的Connector元素,修改属性enableLookups参数值: enableLookups="false",如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址。

<Connector  port="8081" protocol="HTTP/1.1"
               connectionTimeout="6000" enableLookups="false" acceptCount="800"
               redirectPort="8443" />


4.2、jvm调优

优化catalina.sh配置文件。在catalina.sh配置文件中添加以下代码:

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m"

server:一定要作为第一个参数,在多个CPU时性能佳
-Xms:初始堆内存Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
-Xmx:初始堆内存heap最大值,使用的最大内存
上面两个值是分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半。
-XX:PermSize:设定内存的永久保存区域
-XX:MaxPermSize:设定最大内存的永久保存区域
-XX:MaxNewSize:
-Xss 15120 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k.
+XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
-Xss:每个线程的Stack大小
-verbose:gc 现实垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
-XX:+UseParNewGC :缩短minor收集的时间
-XX:+UseConcMarkSweepGC :缩短major收集的时间














5、参考文献

      Tomcat与java web 开发技术详解-孙卫琴-第二版
      深入剖析Tomcat(How Tomcat Works)



Java应用Tomcat执行过程之性能调优