bin:文件是存放启动和关闭tomcat的脚本。
webapps:是存放web应用程序。
work是存放的jsp编译后产生的class文件
conf :存放tomcat相关配置的文件
- Catalina:用于存放每个虚拟机的Context配置
- context.xml 用于定义所有web应用均需要加载的Context配置,如果web定义了自己的context.xml将会被覆盖。
- catalina.properties:tomcat的环境变量的配置。
- catalina.policy tomcat的安全策略配置。
- logging.properties tomcat的日志配置文件,可以通过修改tomcat的日志等级级别和路径
- server.xml tomcat的核心配置文件
- tomcat-uesrs.xml 定义tomcat默认的用户以及角色映射信息配置。
- web.xml:tomcat中所有应用默认的部署描述文件,主要定义了Servlet和MIEME映射。
work目录是存放的jsp代码和临时编译生成的文件。
Tomcat运行原理分析
- Tomcat是运行在jvm的一个进程。它定义为【中间件】。顾名思义,是java项目与jvm之间的一个容器
- WEB项目的本质,是一大堆资源文件和方法。web项目没有main方法,意味着web项目不能自己运行起来。
- web项目部署进tomcat的webapp中的目的很明确,就是希望Tomcat去调用写好的方法为客户端返回需要的资源和数据。
- Tomcat可以运行起来,调用写好的方法,所以tomcat有main方法。
- 对于tomcat而言它并不知道我有什么方法,这些都是在我部署进webapp以后才会确定的,由此分析,必然用到了java的反射来实现动态的加载,实例化,获取方法,调用方法。但是我们部署到tomcat中的方法必须按照一定的接口来编写,以便调用。
server.xml配置文件的主要内容,也是tomcat大容器的结构
<?xml version="1.0" encoding="UTF-8"?>
<!--指的是tomcat服务器一个jvm实例,包含多个组件,负责管理和启动各个service,同时监听8005端口发送的shutdown命令
用于关闭容器。这将意味着各个server不能使用同一个端口
属性:
className: 用于实现此Server容器的完全限定类的名称,默认为org.apache.catalina.core.StandardServer;
port: 接收shutdown指令的端口,默认仅允许通过本机访问,默认为8005;
shutdown:发往此Server用于实现关闭tomcat实例的命令字符串,默认为SHUTDOWN;
-->
<Server port="8005" shutdown="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" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<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>
<!--
定义一个名字为Catalina的service,因此名字也会在产生相关的日志信息时记录在日志文件中
name:此服务的名称,默认为Catalina;
-->
<Service name="Catalina">
<!--
进入tomcat的请求可以分为两类:
一类:tomcat作为应用服务器,请求来自于别的web服务器 这个可能是Apache/IIS/Nignx
就是localhost:80/web/index--经过tomcat转换---tomcat(localhost:8080/web/index.jsp)
另一类:就是直接作为独立服务器--》localhost:8080/web/index.jsp使用浏览器请求
定义连接器可以使用多种属性,有些属性也只适用于某特定的连接器类型。一般说来,常见于server.xml中的连接器类型通常有4种:
1) HTTP连接器 2) SSL连接器 3) AJP 1.3连接器 4) proxy连接器
定义连接器时可以配置的属性非常多,但通常定义HTTP连接器时必须定义的属性只有“port“,
定义AJP连接器时必须定义的属性只有”protocol”,因为默认的协议为HTTP。以下为常用属性的说明:
1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0; 可以自己指定地,如
2) maxThreads:支持的最大并发连接数,默认为200;
3) port:监听的端口,默认为0;
4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;
5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;
6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;
7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false
8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!--使用共享线程池连接-->
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!--定义一个ssl/tls htpp/1.1在8843上的连接,使用nio(同步非阻塞IO)接口,
默认SSLImplementation依赖于ARP/native的包并且使用userOpenSSL监听
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the
AprLifecycleListener.
可以使用JSSE或OpenSSL样式配置,不用管已经配置的SSLImplementation,
下面是JSSE风格的配置
Either JSSE or OpenSSL style configuration may be used regardless of
the SSLImplementation selected. JSSE style configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!--在8443端口定义一个SSL/TLS HTTP/1.1和http/2
这个连接总是使用OpenSSLfor TLS使用APR/native实现。
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!--使用8443端口定义一个AJP1.3 连接-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!--
Engine是Servlet处理器的一个实例,即servlet引擎,
默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一
个接收所有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的.
Engine容器中可以包含Realm、Host、Listener和Valve子容器。
-->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!--
一个Realm表示一个安全上下文,它是一个授权访问某个给定Context的用户列
表和某用户所允许切换的角色相关定义的列表。因此,Realm就像是一个用户和组相关的数据库。
定义Realm时惟一必须要提供的属性是classname,
它是Realm的多个不同实现,用于表示此Realm认证的用户及角色等认证信息的存放位置。
JAASRealm:基于Java Authintication and Authorization Service实现用户认证;
JDBCRealm:通过JDBC访问某关系型数据库表实现用户认证;
JNDIRealm:基于JNDI使用目录服务实现认证信息的获取;
MemoryRealm:查找tomcat-user.xml文件实现用户信息的获取;
UserDatabaseRealm:基于UserDatabase文件(通常是tomcat-user.xml)实现用户认证,它实现是一个完全可更新和持久有效的MemoryRealm,因此能够跟标准的MemoryRealm兼容;它通过JNDI实现;
-->
<!--
使用LockOutRealmz阻止攻击者使用密码暴力攻击
Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the 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=”www.ttlsa.com” appBase=”webapps” unpackWARs=”true”>
<Alias>feiyu.com</Alias>
</Host>
-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!--
1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,
起始路径为此Context所属Host中appBase定义的路径;
切记,docBase的路径名不能与相应的 Host中appBase中定义的路径名有包含关系,
比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
2) path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;
如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;
3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;
-->
<!--
Valve类似于过滤器,它可以工作于Engine和Host/Context之间、
Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,
而且Valve定义的次序也决定了它们生效的次序。Tomcat中实现了多种不同的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>
![6bc2ec35801f680bd6dd9d29be0c49da.png](https://i-blog.csdnimg.cn/blog_migrate/9542c8875f0c7e278a6d02bc47121a34.jpeg)
![cc5886638d57b09d5f95e331b533f99b.png](https://i-blog.csdnimg.cn/blog_migrate/16796f633a43874563b2bc9b0c7f0950.jpeg)
描述:localhost:8080/web/index.jsp
- 当一个请求到达8l,8080被在那里监听的Coyote HTTP/1.1 Connector获得
- Connector把该请求交给它所在的Service的Engine处理,并且等待回应。
- Engine获得locahost/web/index.jsp匹配虚拟主机host
- Host(默认匹配),匹配到路径为web的Context,如果匹配不到默认为”/“的路径
- path="/web"的Context获得请求/index.jsp,在他的mapping table中寻找对应的sevlet。context匹配到URL PATTERN为*.jsp的servlet,对应的servlet类
- 构造HttpServletRequest和HttpServletResponse对象,作为参数调用JSPSevlet中的doGet()/doPost(),执行具体的业务逻辑
- 把Context执行完的HttpServletResponse返回给Host
- Host把带有HttpServletResponse返回给Engine
- Engine把带有HttpServletResponse返回给Connetor
- Connetor把带有HttpServletResponse返回给浏览器
Tomcat各类Connector对比
![d3b6d19f1c4004286b9db9c04af17b5c.png](https://i-blog.csdnimg.cn/blog_migrate/daaf4e81cc4590c0e6886f6dcbe99ba9.jpeg)
Connector的实现模式有三种,分别是BIO、NIO、APR,可以在server.xml中指定。
- BIO:用http://java.io编写的TCP模块,阻塞IO
- NIO:用java.nio编写的TCP模块,非阻塞IO,(IO多路复用)
- APR:全称Apache Portable Runtime,使用JNI的方式来进行读取文件以及进行网络传输
Apache Portable Runtime是一个高度可移植的库,它是Apache HTTP Server 2.x的核心。 APR具有许多用途,包括访问高级IO功能(如sendfile,epoll和OpenSSL),操作系统级功能(随机数生成,系统状态等)和本地进程处理(共享内存,NT管道和Unix套接字)。
表格中字段含义说明:
- Support Polling:是否支持基于IO多路复用的socket事件轮询
- Polling Size:轮询的最大连接数
- Wait for next Request:在等待下一个请求时,处理线程是否释放,BIO是没有释放的,所以在keep-alive=true的情况下处理的并发连接数有限
- Read Request Headers:由于request header数据较少,可以由容器提前解析完毕,不需要阻塞
- Read Request Body:读取request body的数据是应用业务逻辑的事情,同时Servlet的限制,是需要阻塞读取的
- Write Response:跟读取request body的逻辑类似,同样需要阻塞写
NIO Connector主要参数
![d23d1da2a1748b4b8985cb54357c6ef8.png](https://i-blog.csdnimg.cn/blog_migrate/aa3a11db1ae287ae9673b807fb8b918b.jpeg)