4.3 执行器executor
执行器定义tomcat各组件之间共享的线程池。在以前,每个connector都会独自创建自己的线程池,但现在,可以定义一个线程池,各组件都可以共享该线程池,不过主要是为各connector之间提供共享。注意,executor创建的是共享线程池,如果某个connector不引用executor创建的线程池,那么该connector仍会根据自己指定的属性创建它们自己的线程池。
连接器必须要实现org.apache.catalina.Executor接口。它是一个嵌套在service组件中的元素,为了挑选所使用的connector,该元素还必须定义在connector元素之前。
默认的定义如下:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
其中该组件的属性有:
className
:用于实现此组件的Java类的名称,这个类必须实现接口org.apache.catalina.Executor。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardThreadExecutor;name
:该线程池的名称,其他组件需要使用该名称引用该线程池。
标准类的属性包括:
threadPriority
:线程优先级,默认值为5。daemon
:线程是否以daemon的方式运行,默认值为true。namePrefix
:执行器创建每个线程时的名称前缀,最终线程的名称为:namePrefix+threadNumber。maxThreads
:线程池激活的最大线程数量。默认值为200。minSpareThreads
:线程池中最少空闲的线程数量。默认值为25。maxIdleTime
:在空闲线程关闭前的毫秒数。除非激活的线程数量小于或等于minSpareThreads的值,否则会有空闲线程的出现。默认值为60000,即空闲线程需要保留1分钟的空闲时间才被杀掉。maxQueueSize
:可执行任务的最大队列数,达到队列上限时的连接请求将被拒绝。prestartminSpareThreads
:在启动executor时是否立即创建minSpareThreads个线程数,默认为false,即在需要时才创建线程。
例如在connector中指定所使用的线程池,方式如下:
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
4.4 连接器connector
连接器用于接收客户端发送的请求并返回响应给客户端。一个service中可以有多个connector。有多种connector,常见的为http/1.1,http/2和ajp(apache jserv protocol)。在tomcat中,ajp连接协议类型专用于tomcat前端是apache反向代理的情况下。
因此tomcat可以扮演两种角色:
- Tomcat仅作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;
- Tomcat既作为web服务器,也作为应用程序服务器:请求来自于浏览器。
Tomcat应该考虑工作情形并为相应情形下的请求分别定义好需要的连接器才能正确接收来自于客户端的请求。
此处暂先介绍HTTP/1.1连接器的属性设置。ajp后文再做介绍。
HTTP连接器表示支持HTTP/1.1协议的组件。设置了该连接器就表示catalina启用它的独立web服务功能,当然,肯定也提供它必须的servlets和jsp执行功能。在一个service中可以配置一个或多个连接器,每个连接器都可以将请求转发给它们相关联的engine以处理请求、创建响应。
如果想要配置某个web server的连接器,则使用AJP协议。
每个流入的请求都需要一个独立的线程来接收。当并发请求数量超出maxThreads指定的值时,多出的请求将被堆叠在套接字中,直到超出acceptCount指定的值。超出accpetCount的请求将以"connection refused"错误进行拒绝。
默认的定义如下:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
HTTP连接器的属性实在太多,详细配置方法见官方手册。通常定义HTTP连接器时必须定义的属性只有"port"。
address
:指定连接器监听的地址,默认为所有地址,即0.0.0.0。maxThreads
:支持的最大并发连接数,默认为200;如果引用了executor创建的共享线程池,则该属性被忽略。acceptCount
:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;maxConnections
:允许建立的最大连接数。acceptCount和maxThreads是接受连接的最大线程数。存在一种情况,maxConnections小于acceptCount时,超出maxConnections的连接请求将被接收,但不会与之建立连接。port
:监听的端口,默认为0,此时表示随机选一个端口,通常都应该显式指定监听端口。protocol
:连接器使用的协议,用于处理对应的请求。默认为HTTP/1.1,此时它会自动在基于Java NIO或APR/native连接器之间进行切换。定义AJP协议时通常为AJP/1.3。redirectPort
:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口。connectionTimeout
:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;注意,这时候连接已经建立。keepAliveTimeout
:长连接状态的超时时间。超出该值时,长连接将关闭。enableLookups
:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true,应设置为false防止反解客户端主机;compression
:是否压缩数据。默认为off。设置为on时表示只压缩text文本,设置为force时表示压缩所有内容。应该在压缩和sendfile之间做个权衡。useSendfile
:该属性为NIO的属性,表示是否启用sendfile的功能。默认为true,启用该属性将会禁止compression属性。
当协议指定为HTTP/1.1时,默认会自动在NIO/APR协议处理方式上进行按需切换,如要显式指定协议,方式如下:
<connector port="8080" protocol="HTTP/1.1">
<connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol">
其中NIO是C/C++的非阻塞IO复用模型在JAVA中的IO实现,NIO2即AIO是异步NIO,即异步非阻塞IO:
NioProtocol :non blocking Java NIO connector
Nio2Protocol:non blocking Java NIO2 connector
AprProtocol :the APR/native connector
它们之间的异同点如下表所示:
Java Nio Connector | Java Nio2 Connector | APR/native Connector | |
---|---|---|---|
Classname | Http11NioProtocol | Http11Nio2Protocol | Http11AprProtocol |
Tomcat Version | 6.x onwards | 8.x onwards | 5.5.x onwards |
Support Polling | YES | YES | YES |
Polling Size | maxConnections | maxConnections | maxConnections |
Read Request Headers | Non Blocking | Non Blocking | Non Blocking |
Read Request Body | Blocking | Blocking | Blocking |
Write Response Headers and Body | Blocking | Blocking | Blocking |
Wait for next Request | Non Blocking | Non Blocking | Non Blocking |
SSL Support | Java SSL or OpenSSL | Java SSL or OpenSSL | OpenSSL |
SSL Handshake | Non blocking | Non blocking | Blocking |
Max Connections | maxConnections | maxConnections | maxConnections |
下面是一个定义了多个属性的SSL连接器:
<Connector port="8443"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
4.5 容器类engine
engine是service组件中用来分析协议的引擎机器,它从一个或多个connector上接收请求,并将请求交给对应的虚拟主机进行处理,最后返回完整的响应数据给connector,通过connector将响应数据返回给客户端。
只有一个engine元素必须嵌套在每个service中,且engine必须在其所需要关联的connector之后,这样在engine前面的connector都可以被此engine关联,而在engine后面的connector则被忽略,因为一个service中只允许有一个engine。
定义方式大致如下:
<Engine name="Catalina" defaultHost="localhost">
</Engine>
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA">
</Engine>
常用的engine属性有:
className
:实现engine的类,该类必须实现org.apache.catalina.Engine接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardEngine。defaultHost
:指定处理请求的默认虚拟主机。在Engine中定义的多个虚拟主机的主机名称中至少有一个跟defaultHost定义的主机名称同名。name
:Engine组件的名称,用于记录日志和错误信息,无关紧要的属性,可随意给定。jvmRoute
:在启用session粘性时指定使用哪种负载均衡的标识符。所有的tomcat server实例中该标识符必须唯一,它会追加在session标识符的尾部,因此能让前端代理总是将特定的session转发至同一个tomcat实例上。
注意,jvmRoute同样可以使用jvmRoute的系统属性来设置。如果此处设置了jvmRoute,则覆盖jvmRoute系统属性。关于jvmRoute的使用,在后面tomcat ajp负载均衡的文章中介绍。
engine是容器中的顶级子容器,其内可以嵌套一个或多个Host作为虚拟主机,且至少一个host要和engine中的默认虚拟主机名称对应。除了host,还可以嵌套releam和valve组件。
4.6 容器类host
host容器用来定义虚拟主机。engine从connector接收到请求进行分析后,会将相关的属性参数传递给对应的(筛选方式是从请求首部的host字段和虚拟主机名称进行匹配)虚拟host进行处理。如果没有合适的虚拟主机,则传递给默认虚拟主机。因此每个容器中必须至少定义一个虚拟主机,且必须有一个虚拟主机和engine容器中定义的默认虚拟主机名称相同。
大致定义方式如下:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
常用属性说明:
className
:实现host容器的类,该类必须实现org.apache.catalina.Host接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardHost。name
:虚拟主机的主机名,忽略大小写(初始化时会自动转换为小写)。可以使用前缀星号通配符,如"*.a.com"。使用了星号前缀的虚拟主机的匹配优先级低于精确名称的虚拟主机。appBase
:此Host的webapps目录,即webapp部署在此虚拟主机上时的存放目录。包括非归档的web应用程序目录和归档后的WAR文件的目录。使用相对路径时基于$CATALINA_BASE。xmlBase
:部署在此虚拟主机上的context xml目录。startStopThreads
:启动context容器时的并行线程数。如果使用了自动部署功能,则再次部署或更新时使用相同的线程池。autoDeploy
:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy或自动更新部署状态。这等于同时开启了deployOnStartup属性和reload/redeploy webapp的功能。触发自动更新时将默认重载该webapp。默认为true。unpackWars
:在执行此webapps时是否先对归档格式的WAR文件解压再运行,设置为false时则直接执行WAR文件;默认为true。设置为false时会损耗性能。workDir
:该虚拟主机的工作目录。每个webapp都有自己的临时IO目录,默认该工作目录为$CATALINA_BASE/work。
大多数时候都只需设置虚拟主机名称name和webBase属性即可,其余采用默认,默认时会自动部署webapp。有时候还需要管理多个站点名称,即主机别名。可以使用Alias为Host指定的主机名定义主机别名。如:
<Host name="web.a.com" appBase="webapps" unpackWARs="true">
<Alias>www.a.com</Alias>
</Host>
自动部署指的是自动装载webapp以提供相关webapp的服务。
4.7 容器类context
connector和containor是整个tomcat的心脏,而context则是containor的心脏,更是tomcat心脏的心脏。它是真正管理servlet的地方,它的配置影响了servlet的工作方式。
一个context代表一个webapp。servlet中规定,每个webapp都必须基于已归档的WAR(WEB application archive)文件或基于非归档相关内容所在目录。
catalina基于对请求URI与context中定义的path进行最大匹配前缀的规则进行挑选,从中选出使用哪个context来处理该HTTP请求。这相当于nginx的location容器,catalina的path就相当于location的path,它们的作用是相同的。
每个context都必须在虚拟主机容器host中有一个唯一的context name。context的path不需要唯一,因为允许同一个webapp不同版本的共存部署。此外,必须要有一个context的path为0长度的字符串(即<Context path="" docBase="ROOT"/>
),该context是该虚拟主机的默认webapp,用于处理所有无法被虚拟主机中所有context path匹配的请求。
关于context name,它是从context path推断出来的,不仅如此,其余几个属性如context basefile name也是由此推断出来的。规则如下:
- 如果path不为空,则context name等于context path,basefile name取path中去除前缀"/"后的路径,且所有"/"替换为"#"。
- 如果path为空,则context name也为空,而basefile为ROOT(注意是大写)。
例如:
context path context name basefile name deploy examples
-----------------------------------------------------------------
/foo /foo foo foo.xml,foo.war,foo
/foo/bar /foo/bar foo#bar foo#bar.xml,foo#bar.war,foo#bar
Empty String Empty String ROOT ROOT.xml,ROOT.war,ROOT
配置context时,强烈建议不要定义在server.xml中,因为定义conf/server.xml中时,只能通过重启tomcat来重载生效,也就是说无法自动部署应用程序了。虽说官方如此推荐,但大多数人出于习惯和方便,还是会直接写在server.xml中,这并没有什么问题,无非是重启一下而已。
可以考虑定义在/META-INF/context.xml中,如果此时设置了copyXML属性,在部署时会将此context.xml复制到$CATALINA_BASE/conf/enginename/hostname/下,并重命名为"basefile name.xml"。也可以直接定义在$CATALINA_BASE/conf/enginename/hostname/下的.xml文件中,该路径的xml优先级高于/META-INF/context.xml。
还可以定义默认的context.xml文件,包括两种:(1)定义在$CATALINA_BASE/conf/context.xml中,该默认context对所有webapp都生效;(2)定义在$CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default中,该默认context只对该虚拟主机中的所有webapp生效。
定义方式大致如下:
<Host name="www.a.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT"/>
<Context path="/bbs" docBase="web/bbs" reloadable="true"/>
</Host>
其中第一个context的path为空字符串,表示它是默认的context。当浏览器中输入www.a.com时,由于无法匹配第二个context,所以被默认即第一个context处理,当浏览器中输入www.a.com/bbs时,将被第二个context处理,它将执行web/bbs所对应的webapp,并返回相关内容。
在context容器中可以定义非常多的属性,详细内容见官方手册,以下是常见的几个属性:
className
:实现host容器的类,该类必须实现org.apache.catalina.Context接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardContext。cookies
:默认为true,表示启用cookie来标识session。docBase
:即DocumentRoot,是该webapp的context root,即归档WAR文件所在目录或非归档内容所在目录。可以是绝对路径,也可以是相对于该webapp appBase的相对路径。path
:定义webapp path。注意,当path=""时,表示默认的context;另外只有在server.xml中才需要定义该属性,其他所有情况下都不能定义该属性,因为会根据docBase和context的xml文件名推断出path。reloadable
:是否监控/WEB-INF/class和/WEB-INF/lib两个目录中文件的变化,变化时将自动重载。在测试环境下该属性很好,但在真实生产环境部署应用时不应该设置该属性,因为监控会大幅增加负载,因此该属性的默认值为false。wrapperClass
:实现wrapper容器的类,wrapper用于管理该context中的servlet,该类必须实现org.apache.catalina.Wrapper接口,如果不指定该属性则采用默认的标准类。xmlNamespaceAware
:和web.xml的解析方式有关。默认为true,设置为false可以提升性能。xmlValidation
:和web.xml的解析方式有关。默认为true,设置为false可以提升性能。
4.8 被嵌套类realm
realm定义的是一个安全上下文,就像是以哪种方式存储认证时的用户和组相关的数据库。有多种方式可以实现数据存放:
- JAASRealm:基于Java Authintication and Authorization Service实现用户认证;
- JDBCRealm:通过JDBC访问某关系型数据库表实现用户认证;
- JNDIRealm:基于JNDI使用目录服务实现认证信息的获取;
- MemoryRealm:查找tomcat-user.xml文件实现用户信息的获取;
- UserDatabaseRealm:基于UserDatabase文件(通常是tomcat-user.xml)实现用户认证,它实现是一个完全可更新和持久有效的MemoryRealm,因此能够跟标准的MemoryRealm兼容;它通过JNDI实现;
下面是一个常见的使用UserDatabase的配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
下面是一个使用JDBC方式获取用户认证信息的配置:
<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost/authority"
connectionName="test" connectionPassword="test"
userTable="users" userNameCol="user_name"
userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />
4.9 被嵌套类valve
Valve中文意思是阀门,类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。
有多种不同的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进行工作;
其中RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能。如下面的Valve实现了仅允许本机访问/probe:
<Context privileged="true" path="/probe" docBase="probe">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1"/>
</Context>
其中相关属性定义有:
- className:在对应位置的后缀上加上".valves.RemoteHostValve"或".valves.RemoteAddrValve";
- allow:以逗号分开的允许访问的IP地址列表,支持正则,点号“.”用于IP地址时需要转义;仅定义allow项时,非明确allow的地址均被deny;
- deny: 以逗号分开的禁止访问的IP地址列表,支持正则;使用方式同allow;仅定义deny项时,非明确deny的地址均被allow;
另外一个常用的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" />
其中prefix和suffix表示日志文件的前缀名称和后缀名称。pattern表示记录日志时的信息和格式。
更多Tomcat相关教程见以下内容:
CentOS 6.6下安装配置Tomcat环境 http://www.linuxidc.com/Linux/2015-08/122234.htm
RedHat Linux 5.5安装JDK+Tomcat并部署Java项目 http://www.linuxidc.com/Linux/2015-02/113528.htm
Tomcat权威指南(第二版)(中英高清PDF版+带书签) http://www.linuxidc.com/Linux/2015-02/113062.htm
Tomcat 安全配置与性能优化 http://www.linuxidc.com/Linux/2015-02/113060.htm
Linux下使用Xshell查看Tomcat实时日志中文乱码解决方案 http://www.linuxidc.com/Linux/2015-01/112395.htm
CentOS 64-bit下安装JDK和Tomcat并设置Tomcat开机启动操作步骤 http://www.linuxidc.com/Linux/2015-01/111485.htm
Ubuntu 16.04下安装Tomcat 8.5.9 http://www.linuxidc.com/Linux/2017-06/144809.htm
Ubuntu 16.04安装Tomcat 8 图解 http://www.linuxidc.com/Linux/2017-10/147773.htm
Tomcat单机多实例部署-多项目部署 http://www.linuxidc.com/Linux/2017-10/147259.htm
Tomcat 的详细介绍:请点这里
Tomcat 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/148003.htm