tomcat的启动流程及原理

参考自:https://blog.csdn.net/sunyunjie361/article/details/58588033

组件介绍:

Tomcat 最重要的是两个组件是:Connector(连接器) 和 Container(容器/集装箱),Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个 Container 可以选择对应多个 Connector。

多个 Connector 和一个 Container 就组成一个 Service,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境, Server 就提供了这样一个环境。所以整个 Tomcat 的生命周期由 Server 控制。

tomcat核心组件.JPG

下面来一层层的看,首先是Server,什么是server呢?

Server

Server 要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到 Service 集合,同时要维护它所包含的所有 Service 的生命周期,包括如何初始化如何结束服务如何找到别人要访问的 Service。还有一些次要的任务,如记录Service运行日志,维护Session等等。Server包含的组件结构如下:

tomcat-Server.png

Service

Service 是在 Connector 和 Container 外面多包一层,把它们组装在一起,向外面提供服务,一个 Service 可以设置多个 Connector,但是只能有一个 Container 容器。当然Service不仅仅包含这两个组件, Service 接口的方法列表如下:


tomcat-Service方法.png

Container

Container本意是集装箱的意思,是一个接口,定义了下属的各种容器,重要的是Wrapper、Host、Engine、Context等


tomcat-container结构.png
tomcat-container类图.png

Engine(引擎)

负责处理来自相关联的service的所有请求,处理后,将结果返回给service,而connector是作为service与engine的中间媒介出现的。
一个engine下可以配置一个默认主机,每个虚拟主机都有一个域名。当engine获得一个请求时,它把该请求匹配到虚拟主机(host)上,然后把请求交给该主机来处理。
Engine有一个默认主机,当请求无法匹配到任何一个虚拟主机时,将交给默认host来处理。Engine以线程的方式启动Host。

Host

代表一个虚拟主机,每个虚拟主机和某个网络域名(Domain Name)相匹配。
每个虚拟主机下都可以部署一个或多个web应用,每个web应用对应于一个context,有一个context path。
当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理匹配的方法是“最长匹配”,所以一个path==””的Context将成为该Host的默认Context所有无法和其它Context的路径名匹配的请求都将最终和该默认Context匹配。

Context

一个Context对应于一个Web应用,一个Web应用由一个或者多个Servlet组成Context在创建的时候将根据配置文件$CATALINA_HOME/conf/web.xml$ WEBAPP_HOME/WEB-INF/web.xml载入Servlet类。当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类,如果找到,则执行该类,获得请求的回应,并返回。

Wrapper

Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。
Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。

Connector

Connector将在某个指定的端口上来监听客户的请求,把从socket传递过来的数据,封装成Request,传递给Engine来处理,并从Engine处获得响应并返回给客户。

Tomcat通常会用到两种Connector:

  1. Http Connector 在端口8080处侦听来自客户browser的http请求。 AJP Connector
  2. 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求。

Lifecycle

现实生活中大部分的事物都有生命周期,就像人的生老病死一样。

在编程中也有很多对象是具有生命周期的,从初始化、运行、回收等 会经历几个不同的阶段。 在tomcat中容器相关的好多组建都实现了Lifecycle接口,当tomcat启动时,其依赖的下层组件会全部进行初始化。 并且可以对每个组件生命周期中的事件添加监听器

例如当服务器启动的时候,tomcat需要去调用servlet的init方法和初始化容器等一系列操作,而停止的时候,也需要调用servlet的destory方法。而这些都是通过org.apache.catalina.Lifecycle接口来实现的。由这个类来制定各个组件生命周期的规范。


Lifecycle类图.png
tomcat生命周期类分析.png

LifecycleListener

在Lifecycle的介绍中提到,Lifecycle会对每个组件生命周期中的事件添加监听器,也就是addLifecycleListener(LifecycleListener listener)方法,而LifecycleListener就是上面提到的监听器。

LifecycleEvent

顾名思义,就是当有监听事件发生的时候,LifecycleEvent会存储时间类型和数据

/**
* Construct a new LifecycleEvent with the specified      parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
* @param data Event data (if any)
*/
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
   super(lifecycle);
   this.type = type;
   this.data = data;
}

tomcat 的启动过程

tomcat的启动的起点是Server.start()方法,在这里它会依次启动ContainerConnector相关组件,最后到达EndPoint(Tomcat启动的Socket管理者),完成整个启动过程。如下图是个简易过程:

tomcat启动流程.JPG

具体实现过程

StartFirst

/**
 * Start the server.
 *
 * @throws LifecycleException Start error
 */
public void start() throws LifecycleException {
    getServer();
    getConnector();
    server.start();
}

server启动之前需要准备好Server和Connector,server的默认实现是StandardServer, start()方法在其父类LifecycleBase中


tomcat-LifecycleBase的start方法.png

注:LifecycleBase还是StandardService, StandardEngine, StandardHost, StandardContext等的父类,所以当调用这些类的start()方法时其实都是调用此处的start()方法,而最重要的是在start()方法中会调用startInternal()startInternal()在LifecycleBase中是抽象方法,具体实现由各个实现类自己定义。

startServer

启动server其实就是启动service容器,靠StandardService中的startInternal()实现方法,参考代码如下:


tomcat-启动service容器.png

startService

启动service其实就是启动engine容器和connector容器,是在StandardEngine中实现的。参考代码如下:


tomcat-engine和connector容器准备.png

启动Engine

启动engine其实就是启动host容器(多线程),是在StandardHost中实现,参考代码如下:


tomcat-host容器准备.png

启动Host

启动Host的方式和上图一样,都是以线程的方式启动子Container,这里Host的children为Context

启动Context(上下文)

启动Wrapper

tomcat-启动Wrapper.png

loadServlet(加载servlet):

loadServlet1.png

loadServlet2.png

loadServlet3.png

它基本上描述了对 Servlet 的操作,当装载了 Servlet 后就会调用 Servlet 的init 方法,同时会传一个 StandardWrapperFacade对象给 Servlet,这个对象包装了 StandardWrapper,ServletConfig 与它们的关系图如下:

tomcat-ServletConfig类关系.png

启动Connector

Tomcat的Connector是Coyote connector的一种实现,这是tomcat的官方解释:The Coyote HTTP/1.1 Connector element represents a Connector component that supports the HTTP/1.1 protocol. It enables Catalina to function as a stand-alone web server, in addition to its ability to execute servlets and JSP pages.
Tomcat8之后默认使用nio作为接受请求策略,默认在Service启动的时候进行初始化,当然也可以单独启动,在默认的构造函数中会初始化ProtocolHandler

tomcat-connector构造.png

tomcat中支持两种协议的连接器:HTTP/1.1与AJP/1.3

HTTP/1.1协议负责建立HTTP连接,web应用通过浏览器访问tomcat服务器用的就是这个连接器,默认监听的是8080端口;

AJP/1.3协议负责和其他HTTP服务器建立连接,监听的是8009端口,比如tomcat和apache或者iis集成时需要用到这个连接器。


配置协议连机器.png

Connector的启动其实就是ProtocolHandler的启动,如下图:

connector启动.png

ProtocolHandler的类结构如下图:


ProtocolHandler的类结构.png

ConnectorstartInternal方法调用了ProtocolHandlestart方法,这个start方法就在AbstractProtocol中,如下图:

ProtocolHandle-start.png

EndPoint启动

EndPoint是tomcat启动的终点,EndPoint是Tomcat启动的Socket管理者(注:通过类图可以看出AbstractEndpoint已经脱离了Lifecycle和LifecycleListener体系,所以它只是一个简简单单的Socket管理者),因为是由他直接启动默认的Nio,在启动的时候先看看类结构图:

EndPoint类关系.png

EndPoint能做什么呢?来看一下他的方法:

EndPoint的方法.png

createAcceptorcreateExecutor等方法都是在初始化EndPoint很重要方法,因为在接收请求的时候,通过Acceptor的接收,经过重重模块,才能一路到达Servlet
那么EndPoint的启动,如下图:
tomcat-Endpoint启动.png

在这个地方会启动很多的线程,这些线程大多是用于tomcat接收请求的作用。关于tomcat的接收请求流程,后续会继续积累。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容