Tomcat是如何启动及运行—对tomcat的源码解析
Posted ningdunquan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat是如何启动及运行—对tomcat的源码解析相关的知识,希望对你有一定的参考价值。
本文是我阅读了Tomcat源码后的一些心得。主要是讲解Tomcat的系统框架,启动流程已经运行过程。若有错漏之处,敬请批评指教。
先给出几个问题:
tomcat作为一个应用服务器的程序入口在哪里?
tomcat的整体组件结构是什么样的?
tomcat是什么时候及如何创建线程来处理请求的?
tomcat的配置文件context.xml,server.xml,tomcat-users.xml,web.xml什么时候加载的及作用是什么?
最后,tomcat是如何启动运行的?
我通过源码来分析这些问题。
tomcat作为最常见的应用服务器,对ServerSocket、Socket封装使用TCP链接达到通信的目的,我从它的程序入口开始跟踪代码,看它是如何启动的。
Tomcat组件有Server,Service,Container,Connector,Engine,Host,Context,ProtocolHandler,EndPoint等
Server:一个Server元素代表一整个CatalinaServlet容器,也就是说Server是最顶级的容器,它包含一个或多个Service,这个在后面我们可以看到;
Service:由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求;
Connector:连接器,一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户;
Engine:当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理;
Host:当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理;
Context:一个Context对应于一个WebApplication,一个WebApplication由一个或者多个Servlet组成(这个就是我们熟悉的上下文对象了);
Container:是Engine,Host,Context的父类或父接口,这里使用了Composite组合模式,调用它们的start()方法时都会调用父类的此方法;
ProtocolHandler:协议处理器,连接器持有用来控制网络端口监听组件运行;
EndPoint:负责监控网络端口的组件,启动一个ServerSocket,不间断监听来自客户端的请求。
当我们启动Tomcat时:程序会找到Bootstrap的main()方法,同时把args置为["start"]:
然后程序会执行init()方法,设置tomcat运行的环境,初始化类加载器,创建Catalina对象:
接下来程序会执行load()和start()方法,这是tomcat启动过程中最重要的两个过程,load()其实是初始化一系列的组件,上面所列的组件都会进行初始化,包括加载配置文件都是在这个过程中实现的;而start()方法就是启动这一系列的组件,当所有组件都启动后,tomcat也就启动完成了。
从这里看,Tomcat启动过程可以简化为3个步骤:
1)Bootstrap的init()方法,其实就是设置运行环境和初始化类加载器;
2)Bootstrap的load()方法,加载相关配置文件,初始化几个主要的顶层组件实例,也就是服务器初始化。
3)启动那些有生命周期的组件,监听用户请求,也就是启动服务器。
load()方法其实是通过反射来执行Catalina的load()方法,Catalina的load()方法主要作用:
initDirs()方法初始化tomcat的安装路径;
createStartDigester()方法解析xml文件;
getServer().initialize()方法初始化Server组件。
接下来我们看一下server.xml里面的信息到底是什么?为什么能创建server对象呢?
这个就是server.xml的内容,我们可以清晰的看到server下面包含service,service下面包含connector,connector下面包含engine,host和context,这些就是我们上面所说的tomcat的组件,他们的对应关系也是这样层层包含的关系。
接下来看看Server真正的初始化过程:StandardServer的initialize():
StandardService的initialize():
初始化connector,Connector的initialize():
初始化协议,Http11Protocol的init():
Endpoint的初始化,Endpoint的init():
根据上面的server.xml,connector有两个,所以会初始化两个connector,ProtocolHandler和endpoint;
初始化的流程:
所以我们可以知道Bootstrap#load()—>Catalina#load()—>StandardServer#load()—>StandardService#initialize()—>Connector#initialize()—>Http11Protocol#init()—>Endpoint#init()
至此,tomcat的初始化全部完成。
接下来开始启动tomcat服务器:
回到Bootstrap来,Bootstrap的start()方法通过反射来调用Catalina方法的start()方法
来看看Catalina的start():
StandardServer的start():
下面就看看StandardService对象的start方法:
首先启动Container容器,在server.xml中我们知道Container中含有Engine,Host,Context,所以这里会启动这三个容器,Service中的这个Container是Engine,所以首先会启动Engine,Engine中有Host和Context,它们又都属于Container,所以,这里充分的利用了组合模式,这个过程中会创建background后台守护线程,周期性的检查Session是否超时
然后启动执行器executors,这里executors一般为null
最后启动所有的Connector,这个过程会启动两组ProtocolHandler和Endpoint,这个过程是很重要的一个过程,会创建所有的请求线程池,首先先创建一个Acceptor线程来监听当 以上是关于Tomcat是如何启动及运行—对tomcat的源码解析的主要内容,如果未能解决你的问题,请参考以下文章