1.Tomcat的功能和架构
1.1.Tomcat有两大功能
- Http服务器功能:Socket通信(Tcp/IP),解析Http报文。
- Servlet容器功能:Servlet处理具体的业务请求。
1.2.Tomcat架构
Tomcat是套娃式架构
架构分为:
1. Server:Server容器就是一个Tomcat,其下可能存在多个Service节点。
2. Service:Service是对外部提供服务,一个service有多个Connector和Servlet容器。
3. Engine和Host:Engine组件是Servlet容器Catalina的核心,它支持定义多个Host,虚拟主机允许Tomcat引擎在在一台机器上配置多个域名来分割互不干扰。
4. Context:每个虚拟主机可以支持多个web应用部署,是我们所熟知的Context对象。
5. Wrapper:在上下文中可以部署多个Servlet,并且每个对象都会被封装成Wrapper,一个Wrapper对应Servlet。
1.2.套娃式架构的好处
1. 一层套一层的方式,这样组件的关系清晰明了,便于后期组件的生命周期管理。
2. Tomcat的套娃式架构的组件关系对应XML文件标签,后续在解读xml以及组件的时候更容易理解。
3. 便于子容器集成父容器的一些配置。
2.Tomcat源码的构建
源码自官网下载 https://tomcat.apache.org/download-80.cgi
2.1.构建源码运行
操作步骤:
1. 解压压缩包,新建pom..xml,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.tomcat</groupId>
<artifactId>Tomcat8.5</artifactId>
<name>Tomcat8.5</name>
<version>8.5.23</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.1</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxrpc</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.13.0</version>
</dependency>
</dependencies>
<build>
<finalName>Tomcat8.5</finalName>
<sourceDirectory>java</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>java</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>test</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2. 项目根目录下面新建source,将webapps,conf移入source目录。
3. 给启动类添加VM 参数。
-Dcatalina.home=F:\code\apache-tomcat-8.5.58-src\source
-Dcatalina.base=F:\code\apache-tomcat-8.5.58-src\source
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=F:\code\apache-tomcat-8.5.58-src\source\conf\logging.properties
4. 运行Bootstrap的main函数,访问http://localhost:8080 会有报错如下:添加如下一行代码解决。
3.Tomcat启动源码解析
Tomcat启动分三个阶段 init---load---start
3.1.Tomcat组件的生命周期管理
Tomcat启动涉及到组件的实例化(实例化创建销毁),Tomcat有很多组件,为了统一规范他们的生命周期,Tomcat抽取出来了Lifecycle生命周期接口。
- Lifecycle生命周期接口:
- 组件继承体系:
3.2.Tomcat启动分析
-
init阶段
设置类加载器等一些属性
-
load阶段
初始化阶段:一级一级的初始化(对象的实例化),connector组件endpoint(socket通信端口绑定,尚未accept)
-
start阶段
流程大致如上图。只不过init换成了start
4.Servlet请求分析
当一个servlet请求到来的时候,首先经过的是connector组件,它是用来接收请求的。
该组件接收到请求之后,会把相关请求进行封装,然后传递到engine组件中。
紧跟着,engine组件会锁定对应的host,context以及wrapper,一层层的传递下去,找到最终处理请求
的servlet实例。
请求类执行顺序:
NioEndpoint.startInternal() Poller.run() NioEndpoint.processKey() AbstractEndpoint.processSocket() SocketProcessorBase.run() AbstractProtocol.process() AbstractProcessorLight.process() Http11Processor.service() CoyoteAdapter.service() CoyoteAdapter.postParseRequest() Mapper.map() Mapper.internalMap() CoyoteAdapter.service() StandardEngineValve.invoke() AbstractAccessLogValve.invoke() ErrorReportValve.invoke() StandardHostValve.invoke() AuthenticatorBase.invoke() StandardContextValve.invoke() StandardWrapperValve.invoke() ApplicationFilterChain.doFilter() ApplicationFilterChain.internalDoFilter()