tomcat配置文件目录是conf目录,主要配置文件有5个,下面一个个分析下。
1.context.xml
Context.xml是Tomcat公用的环境配置,tomcat服务器会定时去扫描这个文件。一旦发现文件被修改(时间戳改变了),就会自动重新加载这个文件,而不需要重启服务器。不同于server.xml 文件是不可动态重加载的资源,服务器一旦启动了以后,要修改这个文件,就得重启服务器才能重新加载。
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
//监听web.xml文件,文件变动后重新加载
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
2.web.xml
我们web应用的默认配置文件。比如:
默认Servlet
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
默认JSPServlet
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
Servlet可以处理的请求
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
可以处理的请求类型,只要只贴出部分我们常见的请求类型
json application/json jsonml application/jsonml+json jspf text/plain3.tomcat-users.xml
这个是tomcat自动的应用管理工具Tomcat Manager访问的用户权限配置。
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
<user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
<user username="role1" password="<must-be-changed>" roles="role1"/>
tomcat内部的分为哪几个角色,每个角色可以访问什么资源,这些在哪里看?
在tomcat目录下的webapps\manager\WEB-INF目录下面的web.xml文件。这个就是tomcat自动管理应用的web.xml文件。
其中有security-role节点,定义了有哪些角色
<security-role>
<description>
The role that is required to access the HTML Manager pages
</description>
<role-name>manager-gui</role-name>
</security-role>
<security-role>
<description>
The role that is required to access the text Manager pages
</description>
<role-name>manager-script</role-name>
</security-role>
<security-role>
<description>
The role that is required to access the HTML JMX Proxy
</description>
<role-name>manager-jmx</role-name>
</security-role>
<security-role>
<description>
The role that is required to access to the Manager Status pages
</description>
<role-name>manager-status</role-name>
</security-role>
还有个security-constraint节点定义了每个角色可以访问什么资源
<security-constraint>
<web-resource-collection>
<web-resource-name>HTML Manager interface (for humans)</web-resource-name>
<url-pattern>/html/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-gui</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Text Manager interface (for scripts)</web-resource-name>
<url-pattern>/text/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-script</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>JMX Proxy interface</web-resource-name>
<url-pattern>/jmxproxy/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-jmx</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Status interface</web-resource-name>
<url-pattern>/status/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager-gui</role-name>
<role-name>manager-script</role-name>
<role-name>manager-jmx</role-name>
<role-name>manager-status</role-name>
</auth-constraint>
</security-constraint>
4.jaspic-providers.xml
这个配置文件集成第三方JASPIC身份验证,我们不常用,这里不分析。
5.server.xml
server.xml是tomcat的核心配置文件。先大致看一眼,再分析。
<?xml version="1.0" encoding="UTF-8"?>
//server是顶层元素,只能有一个
<Server port="8005" shutdown="SHUTDOWN">
//监听器
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<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将Connector和Engine包装起来,统一对外提供服务。一个server可以有不同的service
//不同的service监听不同的端口
<Service name="Catalina">
//线程池
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4" />
//Connector监听端口为8080,处理协议HTTP1.1协议
//创建Request和Response对象,然后分配线程让Engine来处理这个请求
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
//处理Connector发送的请求,并把相应返回给Connector
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" />
</Realm>
//虚拟节点,处理对应域名或者ip的请求
<Host name="localhost" appBase="webapps" unpackWARs="true"
autoDeploy="true">
//日志打印
<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>
5.1 server元素
整个配置文件的根元素,代表整个tomcat容器,一个tomcat中只能有一个server元素。Server的作用就是提供一个接口,让客户端能够访问内部Service集合,同时维护所有的Service的生命周期,包括初始化、结束服务以及如何找到客户端要访问的Service。
属性:
- className:server元素对应的处理类,默认是StandardServer。tomcat的server实现类必须实现org.apache.catalina.Server接口
- Port:Tomcat将在这个接口监听关闭服务器的命令
- Shutdown:关闭Tomcat服务器的命令字符串
5.2 Listener元素
Listener就是监听器,监听特定事件发生并执行特定的操作。监听器可以在Server、Engine、Host或Context中。
属性:
- className:监听器的具体实现类,监听器必须实现org.apache.catalina.LifecycleListener接口。
介绍几个常用监听器:
- VersionLoggerListener:Tomcat启动时,记录Tomcat、Java和操作系统的信息,必须配置在第一个
- AprLifecycleListener:Tomcat启动时,检查APR库,如果存在则加载
- JasperListener:Web应用启动之前初始化Jasper。Jasper是JSP引擎,把JSP文件解析成java文件,然后编译成class文件供JVM使用
- JreMemoryLeakPreventionListener:与类加载器导致的内存泄露有关。
- GlobalResourcesLifecycleListener:通过该监听器,初始化GlobalNamingResources标签中定义的全局JNDI资源
- ThreadLocalLeakPreventionListener:当Web应用因ThreadLocal导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新。只有当Context元素的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效
5.3 Service元素
service就是将其内部的Connector和Engine包装起来,统一对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine。其中Connector的作用是从客户端接收请求,然后转交给Engine处理,Engine处理完成后将响应返回给Connector,Connector再返回给客户端。
5.4 Connector元素
Connector就是连接器。作用是接收客户端的连接请求,创建Request和Response对象,然后分配线程让Engine来处理,并把产生的Request和Response对象传给Engine。Engine处理完后将Response返回给Connector,Connector再返回给客户端。
属性:
- allowTrace:是否允许HTTP的TRACE方法,默认为false
- enableLookups:如果为true,调用request.getRemoteHost()远程主机的主机名。如果为false,则直接返回IP地址
- maxPostSize:POST请求的最大数量,没有指定默认为2097152
- protocol:请求协议,比如HTTP1.1,或者AJP/1.3
- redirectPort:重定向端口,比如连机器不支持SSL,请请求转发给这个端口
- secure:SSL连接器中设置为true,默认为false;
- URIEncoding:URL编码,默认为ISO-8859-1;
- acceptCount:当accept队列中连接的个数达到acceptCount时,后续请求一律被拒绝。默认值是100
- bufferSize:输入流缓冲区大小,默认2048字节;
- compressableMimeType:MIME的列表,默认是text/html,text/xml,text/plain;
- compression:是否对响应数据压缩。off是禁止压缩,on是允许压缩。force是所有情况下都进行压缩,默认不压缩
- connectionTimeout:连接超时时间
- maxHttpHeaderSize:HTTP请求和响应头的最大量,默认为4096字节;
- maxKeepAliveRequest:长连接最大数
- port:监听的端口
- maxConnections:Tomcat在任意时刻接收和处理的最大连接数
(1)一个Service可以包含多个Connector,比如```
//处理以http协议访问8080端口的请求,当要求请求是https,但请求是http时,重定向到端口号为8443的Connector
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
//处理以AJP协议访问8009端口的请求。AJP协议负责和其他的HTTP服务器(如Apache)建立连接。
//Tomcat常用来作为Servlet/JSP容器,但是对静态资源的处理速度较慢,不如Apache等HTTP服务器,所以有时会将Tomcat和Apache集成,这时候就会用到这个连接器。
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
(2)Connector重要参数详细说明
Connector是处理客户端连接请求的,分配线程让Engine处理,所以Connector参数的配置直接影响tomcat的性能,这里详细说明下几个重要的参数。
Connector处理请求分为BIO和NIO两种方式。
BiO的处理流程:
客户端通过TCP三次握手和服务器建立连接后,连接请求socket会放入一个accept队列。Connector中主要通过JIoEndpoint对象处理请求,JIoEndpoint对象维护了Acceptor和Worker。Acceptor负责从accept队列接收socket,然后从Worker线程池中找出空闲的线程处理socket。如果没有空闲线程,Acceptor将阻塞。其中如果配置了Executor,使用的是Worker线程池就是Executor,否则是tomcat自带的线程池。
NiO的处理流程:
客户端通过TCP三次握手和服务器建立连接后,连接请求socket会放入一个accept队列。Connector中主要通过NIoEndpoint对象处理请求,NIoEndpoint对象维护了Acceptor、Worker和Poller。Acceptor负责从accept队列接收socket,然后Acceptor将请求放入了一个队列,Poller从队列中消费请求,并将该请求注册到一个Selector选择器,然后轮询Selector找到真正有请求数据的,再从Worker线程池中找出空闲的线程处理socket。如果没有空闲线程则将阻塞。其中如果配置了Executor,使用的是Worker线程池就是Executor,否则是tomcat自带的线程池。
目前大多数HTTP请求使用的是长连接,也就是说socket在当前请求结束后,socket不会立马释放,而是等timeout后再释放,相应的线程会一直被占用。使用BIO,有socket连接后直接交给线程处理,不管有没有读写请求,所以Tomcat同时处理的socket数目不能超过最大线程数,性能受到限制。而使用NIO,socket是注册到Selector选择器,有读写请求后才交给线程处理,所以Tomcat可以同时处理的socket数目可以远大于最大线程数,并发性能大大提高。
acceptCount、maxConnections、maxThreads参数
- acceptCount
accept队列的长度;当accept队列中连接的个数达到acceptCount时,队列满,进来的请求一律被拒绝。默认值是100。 - maxConnections
Tomcat在任意时刻接收和处理的最大连接数。当Tomcat接收的连接数达到maxConnections时,Acceptor线程不会读取accept队列中的连接。这时accept队列中的线程会一直阻塞着,直到Tomcat接收的连接数小于maxConnections。如果设置为-1,则连接数不受限制。
NIO的默认值是10000,APR/native的默认值是8192,而BIO的默认值为maxThreads(如果配置了Executor,则默认值是Executor的maxThreads)。 - maxThreads
处理请求线程的最大数量。默认值是200。如果该Connector绑定了Executor,这个值会被忽略,因为该Connector将使用绑定的Executor,而不是内置的线程池来执行任务。
Executor的主要属性包括
- name:该线程池的标记
- maxThreads:线程池中最大活跃线程数,默认值200(Tomcat7和8都是)
- minSpareThreads:线程池中保持的最小线程数,最小值是25
- maxIdleTime:线程空闲的最大时间,当空闲超过该值时关闭线程(除非线程数小于minSpareThreads),单位是ms,默认值60000(1分钟)
- daemon:是否后台线程,默认值true
- threadPriority:线程优先级,默认值5
- namePrefix:线程名字的前缀,线程池中线程名字为:namePrefix+线程编号
5.5 Engine元素
Engine在Service中只能由一个;Engine是Service组件中的请求处理组件。Engine组件从一个或多个Connector中接收请求并处理,并将完成的响应返回给Connector。
Engine、Host和Context都是容器,Engine包含Host,Host包含Context。Engine中至少有一个Host元素,并且必须有一个Host属性的名字与defaultHost指定的名字相匹配。
属性:
- className:Engine元素的实现类,默认是StandardEngine。实现类必须实现org.apache.catalina.Engine接口
- defaultHost:默认主机名,值必须与Service的name值相匹配
- name:Engine名称
- jvmRoute:在负载匀衡中使用的标识符
5.6 Host元素
Host表示一个虚拟主机。
属性:
- appBase:设定应用程序的基目录,绝对路径或相对于%CATALINA_HOME%的路径名
- autoDeploy:指示Tomcat运行时,如有新的WEB程序在appBase指定的目录下,是否自动布署,默认值为true
- className:Host元素实现类名,默认是StandardHost。Host实现类必须实现org.apache.catalina.Host接口
- deployOnStartup:Tomcat启动时,是否自动部署appBase属性指定目录下所有的WEB应用程序,默认值为true
- name:虚拟主机名称
- deployXML:为false将不会解析WEB应用程序内部的context.xml,默认值为true;
- unPackWARs:是否将Web应用的WAR文件解压
autoDeploy和deployOnStartup区别
- deployOnStartup为true时,Tomcat在启动时检查Web应用,检测到的所有Web应用都是新应用
- autoDeploy为true时,Tomcat在运行时定期检查是否有新的Web应用或Web应用的更新
应用的新增或者更新的检查目录为Host元素的appBase和xmlBase配置。appBase属性指定Web应用所在的目录,默认值是webapps。xmlBase属性指定Web应用的XML配置文件所在的目录,默认值为conf/<engine_name>/<host_name>。
5.7 Context元素
Context代表在特定虚拟主机上运行的一个WEB应用程序,需处理当前WEB应用程序的所有请求,每一个ontext必须使用唯一的上下文路径。
Context是Host的子容器,每个Host中可以定义任意多的Context元素。
属性:
- className:Context元素实现类,默认是StandardContext。Context实现类必须实现org.apache.catalina.Context接口
- cookies:是否将Cookie应用于Session,默认值为true
- crossContext:是否允许跨域访问
- docBase:绝对路径或相对于Host的appBase 属性的相对路径,代表WAR包路径或者应用目录,注意docBase在appBase目录时,不需要指定
- privileged:是否允许Web应用程序使用容器的Servlet
- path:访问该Web应用的上下文路径。一个虚拟主机中,上下文路径必须唯一
- reloadable:Tomcat运行时,如果WEB-INF/classes和WEB-INF/lib目录中有改变,否自动重新加载。对性能影响比较大,慎用
- cacheMaxSize:静态资源缓存最大值,以KB为单位,默认值为10240KB;
- cachingAllowed:是否允许静态资源缓存,默认为true
- caseSensitive:资源文件名大小写是否敏感
- unpackWAR:是否解压war包
- workDir:Servlet指定临时读写的目录
有时候我们的server.xml配置文件中并没有Context元素。这是因为Tomcat开启了自动部署,这时候path属性由配置文件(xmlBase目录下xml文件)的文件名、WAR文件的文件名或应用目录的名称自动推导出来。如果名称是ROOT,则该Web应用是虚拟主机默认的Web应用,此时path属性推导为""。
5.8 Valve元素
Valvee在Tomcat中代表了请求处理流水线上的一个组件,Valve可以与Tomcat的容器Engine、Host或Context关联。不同的Valve有不同的特性,这里介绍一下上面出现的AccessLogValve。
AccessLogValve的作用是通过日志记录其所在的容器中处理的所有请求,在上述文件中Valve放在Host下,可以记录该Host处理的所有请求。
AccessLogValve的属性
- className:Valve实现类
- directory:日志存储的目录
- prefix:日志文件的前缀
- suffix:日志文件的后缀
- pattern:记录日志的格式,%h:远程主机名或IP地址;%l:远程逻辑用户名,一般是”-”;%u:授权的远程用户名,如果没有则是”-”;%t:访问的时间;%r:请求的第一行,即请求方法(get/post等)、uri、及协议;%s:响应状态,如404等等;%b:响应的数据量,不包括请求头,如果为0,则是”-”;%D,含义是请求处理的时间
6.总结
先看下tomcat的架构图
tomcat中只能由一个server,一个server中可以包含多个service,一个service中只能包含一个Engine,可以包含多个Connector,一个Engine可以包含多个host,一个host中可以包含多个Context。
tomcat处理流程:
- 客户端发起请求tomcat容器
- service找到符合端口和协议的Connector执行
- Connector创建Request和Response对象,创建线程,交给Engine执行
- 请求流转到Engine后,会进入它的pipeline组件,并且经过内部Valve的过滤,然后Engine根据访问的域名或者ip找到对应host执行
- 请求流转到Host后,会进入它的pipeline组件中,并且经过内部Valve的过滤,然后host请求路径找到对应的Context下的应用
- 请求流转到Context后,会进入它的pipeline组件中,并且经过内部Valve的过滤,然后交给Wrapper执行
- 请求流转到Wrapper后,会进入它的pipeline组件中,并且经过内部Valve的过滤,Wrapper内部的WrapperValve创建FilterChain实例,调用指定的Servlet实例处理请求
- 最后将请求结果返回