学习了tomcat
的启动流程,我们来学习一下tomcat
的配置文件server.xml
顶级组件Server
代表整个Tomcat
容器,表示一个运行于JVM
中的tomcat
实例,提供一个接口让客户端能够访问到这个Service
集合,
同时维护它所包含的所有的Service
的生命周期,包括如何初始化、如何结束服务、如何找到客户端要访问的Service
,8005端口监听shutdown
命令
1、监听器Listener 组件
<!-- 当Tomcat启动时,用于以日志形式输出Tomcat、JVM和操作系统的信息。该监听器必须是配置的第一个监听器 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Tomcat启动时,检查APR库,如果存在则加载。APR,即Apache Portable Runtime,是Apache可移植运行库,可以实现高可扩展性、高性能,以及与本地服务器技术更好的集成,如果找不到APR库,则会输出日志,并不影响tomcat启动 -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- 在Web应用启动之前初始化Jasper,Jasper是JSP引擎,把JVM不认识的JSP文件解析成java文件,然后编译成class文件供JVM使用 -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- 与类加载器导致的内存泄露有关,避免JRE内存泄漏问题 -->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- 通过该监听器,加载和销毁全局命名服务 -->
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<!-- 当Web应用因thread-local导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新。当线程执行完任务被收回线程池时,
活跃线程会一个一个的更新。只有当Web应用(即Context元素)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效 -->
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
2、Service组件
将连接器Connector
关联至引擎Engine
,因此一个Service
内部可以有多个Connector
,但是只能有一个Engine
2.1 Executor 组件
<Executor name="tomcatThreadPool"
namePrefix="catalina-exec-"
maxThreads="150"
minSpareThreads="4"
maxIdleTime="60000"
maxQueueSize="Integer.MAX_VALUE"
prestartminSpareThreads="false"
threadPriority="5"
className="org.apache.catalina.core.StandardThreadExecutor"/>
用于配置共享线程池,即多个Connector
共享这一个线程池,默认情况下是没有配置的,所以每个Connector
都有一个自己的线程池,配置参数说明:
name:
线程池名称,用于在Connector
中指定;
namePrefix:
所创建的每个线程的名称前缀,一个单独的线程名称为namePrefix + threadNumber
;
maxThreads:
线程池中最大线程数;
minSpareThreads:
活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在,直到线程池被销毁;
maxIdleTime:
线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒;
maxQueueSize:
任务队列中任务的上限,超过则请求拒绝;
prestartminSpareThreads:
是否在Executor
启动时就生成minSpareThreads
个线程;
threadPriority:
线程池中线程优先级,值从1到10,默认为5;
className:
线程池实现类,默认为 org.apache.catalina.core.StandardThreadExecutor
,可以使用自定义的线程池。
2.2 Connector连接器
<!-- Connector接收连接请求,创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine来处理这个请求,并把产生的Request和Response对象传给Engine -->
<!-- http端口地址,协议版本号,超时时间,重定向https请求的端口,指定共享线程池名称, 指定编码URI的字符编码-->
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool" URIEncoding="UTF-8"/>
<!-- ajp端口地址,协议版本号,可应用于apacheJk插件容器的通信 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
2.3 Engine引擎
<!-- 核心容器,catalina引擎,负责通过Connector接收用户请求 -->
<Engine name="Catalina" defaultHost="localhost">
<!-- Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用(暂时没用过) -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<!-- session复制的配置,还需要在tomcat中部署的应用的web.xml中配置<distributable/>,这种方式不适合大量集群 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<!-- 虚拟主机配置相关(虚拟主机名,应用地址,是否以war包形式运行,是否自动部署),Host组件至少有一个,且其中一个的name必须与Engine组件的defaultHost属性相匹配,除默认主机名外,其他定义的主机名需要去专门的DNS服务器申请 -->
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- 省略Context配置,虚拟主机的应用地址下,每个文件夹表示一个应用,ROOT可直接访问,其他的需要加上应用名 -->
<!-- Valve理解为'阀',目前主要有客户访问日志阀,远程地址过滤阀,远程主机过滤阀,客户请求记录阀。AccessLogValve(客户访问日志阀)的作用是通过日志记录其所在的容器中处理的所有请求 -->
<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>
最后将完整的server.xml文件放在这里,供大家学习交流
<!-- 代表整个Tomcat容器,表示一个运行于JVM中的tomcat实例,提供一个接口让客户端能够访问到这个Service集合,
同时维护它所包含的所有的Service的生命周期,包括如何初始化、如何结束服务、如何找到客户端要访问的Service,8005端口监听shutdown命令 -->
<Server port="8005" shutdown="SHUTDOWN">
<!-- 当Tomcat启动时,用于以日志形式输出Tomcat、JVM和操作系统的信息。该监听器必须是配置的第一个监听器 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Tomcat启动时,检查APR库,如果存在则加载。APR,即Apache Portable Runtime,是Apache可移植运行库,可以实现高可扩展性、高性能,以及与本地服务器技术更好的集成,如果找不到APR库,则会输出日志,并不影响tomcat启动 -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- 在Web应用启动之前初始化Jasper,Jasper是JSP引擎,把JVM不认识的JSP文件解析成java文件,然后编译成class文件供JVM使用 -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- 与类加载器导致的内存泄露有关,避免JRE内存泄漏问题 -->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- 通过该监听器,加载和销毁全局命名服务 -->
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<!-- 当Web应用因thread-local导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新。当线程执行完任务被收回线程池时,
活跃线程会一个一个的更新。只有当Web应用(即Context元素)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效 -->
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- GlobalNamingResources元素定义了全局资源,通过配置可以看出,该配置是通过读取$TOMCAT_HOME/conf/tomcat-users.xml实现的 -->
<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>
<!--将连接器Connector关联至引擎Engine,因此一个Service内部可以有多个Connector,但是只能有一个Engine -->
<Service name="Catalina">
<!-- 用于配置共享线程池,即多个Connector共享这一个线程池,默认情况下是没有配置的,所以每个Connector都有一个自己的线程池
name: 线程池名称,用于在Connector中指定
namePrefix: 所创建的每个线程的名称前缀,一个单独的线程名称为namePrefix+threadNumber
maxThreads: 线程池中最大线程数
minSpareThreads: 活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在,直到线程池被销毁
maxIdleTime: 线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒
maxQueueSize: 任务队列中任务的上限,超过则请求拒绝
prestartminSpareThreads: 是否在Executor启动时就生成minSpareThreads个线程
threadPriority: 线程池中线程优先级,值从1到10,默认为5
className: 线程池实现类,默认为org.apache.catalina.core.StandardThreadExecutor,可以使用自定义的线程池-->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE"
prestartminSpareThreads="false" threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor"/>
<!-- Connector接收连接请求,创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine来处理这个请求,并把产生的Request和Response对象传给Engine -->
<!-- http端口地址,协议版本号,超时时间,重定向https请求的端口,指定共享线程池名称, 指定编码URI的字符编码-->
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool" URIEncoding="UTF-8"/>
<!-- ajp端口地址,协议版本号,可应用于apacheJk插件容器的通信 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- 核心容器,catalina引擎,负责通过Connector接收用户请求 -->
<Engine name="Catalina" defaultHost="localhost">
<!-- Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用(暂时没用过) -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<!-- session复制的配置,还需要在tomcat中部署的应用的web.xml中配置<distributable/>,这种方式不适合大量集群 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
<!-- 虚拟主机配置相关(虚拟主机名,应用地址,是否以war包形式运行,是否自动部署),Host组件至少有一个,且其中一个的name必须与Engine组件的defaultHost属性相匹配,除默认主机名外,其他定义的主机名需要去专门的DNS服务器申请 -->
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- 省略Context配置,虚拟主机的应用地址下,每个文件夹表示一个应用,ROOT可直接访问,其他的需要加上应用名 -->
<!-- Valve理解为'阀',目前主要有客户访问日志阀,远程地址过滤阀,远程主机过滤阀,客户请求记录阀。AccessLogValve(客户访问日志阀)的作用是通过日志记录其所在的容器中处理的所有请求 -->
<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>