Tomcat源码解析一 架构初窥
引言
Tomcat
是一个非常复杂的Servlet
容器,也是在日常工作中与我们接触非常多的Http服务器
,作为一个成熟的软件,它的整体设计,代码结构都十分的优秀,作为开发者,非常有必要研读Tomcat
源码。阅读源码总是开头难,但是一旦对整体设计理念有一定了解后,再进行深入分析,就会有不一样的收获。
整体架构
先上一张总体架构图
image.png这张图可以说每篇介绍Tomcat
的博客都是必放,既然每个人都认可这张图,说明此图非常重要。接下来我们就围绕这张图对Tomcat
的整体架构进行分析。
-
Server
服务器:可以看成代表Tomcat服务器本身,一个Tomcat实例只会有一个Server -
Service
查看上图,可知一个Server
可以包含多个Service
,在这里可以把Service
看成是Connector
和Container
组合层,Connector
和Container
是Tomcat两个主要的模块- Connector 连接器,一个
Service
可以有多个Connector
(http AJP 等),监听用户请求端口 - Container 按照层级有
Engine
,Host
,Context
,Wrapper
四种,一个Service
只有一个Engine
,其主要作用是执行业务逻辑
- Connector 连接器,一个
这里我再贴一个Tomcat的配置文件,可以根据此配置文件再回过头去看上图
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<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,并且配置了shutdown
端口为8005
,然后就配置了一个名为Catalina
的Service
,这里其实可以配置多个Service
。再看Service
节点中,配置了多个Connector
连接器,并且配置了一个Engine
,Engine
对应Container
的最顶层,一个Service
只有一个Engine
。
下面我们再进行逐个分析
Server
Server
是Tomcat最顶层的容器,一个Tomcat
实例只会有一个Server
。一个Server
至少需要包含一个Service
,在配置文件中的体现就是至少需要包含一个Service
节点。这里我们可以看下Tomcat对于Server
的标准实现类org.apache.catalina.core.StandardServer
,其中Lifecycle
这个接口是Tomcat
对于生命周期维护的重要接口,每个组件都必须实现,从而保证了统一启动/统一关闭的效果
Service
前文说过,Service
就是用于组装Connector
和Container
的对应关系的。通过查看配置文件,可知Service
节点包含了Connector
和Container
,其中Connector
监听用户请求,并解析请求参数,Container
执行具体业务逻辑
Connector
Connector
是连接器,用于接受请求并将请求封装成Request
和Response
,然后交给Container
进行处理,Container
处理完之后再交给Connector
返回给客户端
Container
Tomcat
中的Servlet
容器必须实现Container
接口,也就是说Servlet容器
都是Container
接口的实例,接下来将会介绍四种类型的容器
- Engine: 表示整个
Servlet
引擎 - Host: 表示包含一个或多个
Context
容器的虚拟主机 - Contetx: 表示一个Web应用程序。一份Context可以有多个Wrapper
- Wrapper: 表示一个独立的servlet
上述的每一个概念都是实现了org.apache.catalina.Container
接口的,这四个实现的标准类分别对应StandardEngine
,StandardHost
,StandardContetx
,StandardWrapper
。我们可以通过下图理清它们的层次关系。一般情况下,一个容器可以有0个或多个低层次的子容器
Engine
Engine
容器表示Tomcat
的整个servlet
引擎。如果使用了Engine
容器,那么它总是处于容器层级的最顶层。添加到Engine容器中的子容器通常是Host
或Context
的实现。默认情况下,tomcat
会使用Engine
容器,并且有一个Host
容器作为其子容器。
Host
Host
表示虚拟主机,如果你想在同一个Tomcat
部署上运行多个Context
容器的话,你就需要使用Host
容器。理论上,当你只有一个Context实例
时,不需要使用Host
实例。但是在Tomcat
的实际部署中,总是会使用一个Host
容器
Context
对应一个独立的Web应用程序
,也就是对应我们日常编写的单独Web应用
Context
容器的父容器通常是Host容器,也有可能是其他实现,或则如果不必要,就可以不使用父容器
Wrapper
Wrapper
封装了一个具体的Servlet
尾言
本文主要分析解读了tomcat
的总体设计架构,tomcat
的源码非常非常的多,如果我们不对其整体架构层次进行分析,直接进行源码阅读,会感觉仿若置身大海,非常的浪费时间。所以若大家有想法阅读tomcat
源码,还是有必要先理清其架构体系