tomcat源码分析之系统框架与启动流程

前言:

  本文是我阅读了TOMCAT源码后的一些心得。主要是讲解TOMCAT的系统框架,以及启动流程。若有错漏之处,敬请批评指教!

建议:

毕竟TOMCAT的框架还是比较复杂的,单是从文字上理解,是不那么容易掌握TOMCAT的框架的。所以得实践、实践、再实践。建议下载一份TOMCAT的源码,调试通过,然后单步跟踪其启动过程。如果有不明白的地方,再来查阅本文,看是否能得到帮助。我相信这样效果以及学习速度都会好很多!

1.Tomcat的整体框架结构

Tomcat的基本框架,分为4个层次。

TopLevelElements:

Server

Service

Connector

HTTP

AJP

Container

Engine

Host

Context

Component

manager

logger

loader

pipeline

valve

...

站在框架的顶层的是Server和Service

Server:

其实就是BackGroud程序,在Tomcat里面的Server的用处是启动和监听服务端事件(诸如重启、关闭等命令。在tomcat的标准配置文件:server.xml里面,我们可以看到“”这里的"SHUTDOWN"就是server在监听服务端事件的时候所使用的命令字)

Service:在tomcat里面,service是指一类问题的解决方案。

通常我们会默认使用tomcat提供的:Tomcat-Standalone模式的service。在这种方式下的service既给我们提供解析jsp和servlet的服务,同时也提供给我们解析静态文本的服务。

Connector:Tomcat都是在容器里面处理问题的,而容器又到哪里去取得输入信息呢?

Connector就是专干这个的。他会把从socket传递过来的数据,封装成Request,传递给容器来处理。

通常我们会用到两种Connector,一种叫httpconnectoer,用来传递http需求的。另一种叫AJP,在我们整合apache与tomcat工作的时候,apache与tomcat之间就是通过这个协议来互动的。(说到apache与tomcat的整合工作,通常我们的目的是为了让apache获取静态资源,而让tomcat来解析动态的jsp或者servlet。)

Container:当httpconnector把需求传递给顶级的container:Engin的时候,我们的视线就应该移动到Container这个层面来了。

在Container这个层,我们包含了3种容器:Engin,Host,Context.

Engin:收到service传递过来的需求,处理后,将结果返回给service(service是通过connector这个媒介来和Engin互动的).

Host:Engin收到service传递过来的需求后,不会自己处理,而是交给合适的Host来处理。

Host在这里就是虚拟主机的意思,通常我们都只会使用一个主机,既“localhost”本地机来处理。

Context:Host接到了从Host传过来的需求后,也不会自己处理,而是交给合适的Context来处理。

比如:

前者交给foo这个Context来处理,后者交给bar这个Context来处理。

很明显吧!context的意思其实就是一个webapp的意思。

我们通常都会在server.xml里面做这样的配置

这个context容器,就是用来干我们该干的事儿的地方的。

Compenent:接下来,我们继续讲讲component是干什么用的。

我们得先理解一下容器和组件的关系。

需求被传递到了容器里面,在合适的时候,会传递给下一个容器处理。

而容器里面又盛装着各种各样的组件,我们可以理解为提供各种各样的增值服务。

manager:当一个容器里面装了manager组件后,这个容器就支持session管理了,事实上在tomcat里面的session管理,就是靠的在context里面装的managercomponent.

logger:当一个容器里面装了logger组件后,这个容器里所发生的事情,就被该组件记录下来啦!我们通常会在logs/这个目录下看见catalina_log.time.txt以及localhost.time.txt和localhost_examples_log.time.txt。这就是因为我们分别为:engin,host以及context(examples)这三个容器安装了logger组件,这也是默认安装,又叫做标配:)

loader:loader这个组件通常只会给我们的context容器使用,loader是用来启动context以及管理这个context的classloader用的。

pipline:pipeline是这样一个东西,当一个容器决定了要把从上级传递过来的需求交给子容器的时候,他就把这个需求放进容器的管道(pipeline)里面去。而需求傻呼呼得在管道里面流动的时候,就会被管道里面的各个阀门拦截下来。比如管道里面放了两个阀门。第一个阀门叫做“access_allow_vavle”,也就是说需求流过来的时候,它会看这个需求是哪个IP过来的,如果这个IP已经在黑名单里面了,sure,杀!第二个阀门叫做“defaul_access_valve”它会做例行的检查,如果通过的话,OK,把需求传递给当前容器的子容器。就是通过这种方式,需求就在各个容器里面传递,流动,最后抵达目的地的了。

valve:就是上面所说的阀门啦。

Tomcat里面大概就是这么些东西,我们可以简单地这么理解tomcat的框架,它是一种自上而下,容器里又包含子容器的这样一种结构。

2.Tomcat的启动流程

这篇文章是讲tomcat怎么启动的,既然我们大体上了解了TOMCAT的框架结构了,那么我们可以望文生意地就猜到tomcat的启动,会先启动父容器,然后逐个启动里面的子容器。启动每一个容器的时候,都会启动安插在他身上的组件。当所有的组件启动完毕,所有的容器启动完毕的时候,tomcat本身也就启动完毕了。

顺理成章地,我们同样可以猜到,tomcat的启动会分成两大部分,第一步是装配工作。第二步是启动工作。

装配工作就是为父容器装上子容器,为各个容器安插进组件的工作。这个地方我们会用到digester模式,至于digester模式什么,有什么用,怎么工作的.请参考

启动工作是在装配工作之后,一旦装配成功了,我们就只需要点燃最上面的一根导线,整个tomcat就会被激活起来。这就好比我们要开一辆已经装配好了的汽车的时候一样,我们只要把钥匙插进钥匙孔,一拧,汽车的引擎就会发动起来,空调就会开起来,安全装置就会生效,如此一来,汽车整个就发动起来了。(这个过程确实和TOMCAT的启动过程不谋而和,让我们不得不怀疑TOMCAT的设计者是在GE做JAVA开发的)。

2.1一些有意思的?疲?

Catalina

Tomcat

Bootstrap

Engin

Host

Context

他们的意思很有意思:

Catalina:远程轰炸机

Tomcat:熊猫轰炸机--轰炸机的一种(这让我想起了让国人引以为豪的熊猫手机,是不是英文可以叫做tomcat???,又让我想起了另一则广告:波导-手机中的战斗机、波音-客机中的战斗机)

Bootstap:引导

Engin:发动机

Host:主机,领土

Context:内容,目标,上下文

...在许多许多年后,现代人类已经灭绝。后现代生物发现了这些单词零落零落在一块。一个自以为聪明的家伙把这些东西翻译出来了:

在地勤人员的引导(bootstrap)下,一架轰炸架(catalina)腾空跃起,远看是熊猫轰炸机(tomcat),近看还是熊猫轰炸机!凭借着优秀的发动机技术(engin),这架熊猫轰炸机飞临了敌国的领土上空(host),对准目标(context)投下了毁天灭地的核弹头,波~现代生物就这么隔屁了~

综上所述,这又不得不让人联想到GE是不是也参与了军事设备的生产呢?

反对美帝国主义!反对美霸权主义!和平万岁!自由万岁!

2.2

历史就是那么惊人的相似!tomcat的启动就是从org.apache.catalina.startup.Bootstrap这个类悍然启动的!

在Bootstrap里做了两件事:

1.指定了3种类型classloader:

commonLoader:common/classes、common/lib、common/endorsed

catalinaLoader:server/classes、server/lib、commonLoader

sharedLoader:

shared/classes、shared/lib、commonLoader

2.引导Catalina的启动。

用Reflection技术调用org.apache.catalina.startup.Catalina的process方法,并传递参数过去。

2.3Catalina.java

Catalina完成了几个重要的任务:

1.使用Digester技术装配tomcat各个容器与组件。

1.1装配工作的主要内容是安装各个大件。比如server下有什么样的servcie。Host会容纳多少个context。Context都会使用到哪些组件等等。

1.2同时呢,在装配工作这一步,还完成了mbeans的配置工作。在这里,我简单地但不十分精确地描述一下mbean是什么,干什么用的。

我们自己生成的对象,自己管理,天经地义!但是如果我们创建了对象了,想让别人来管,怎么办呢?我想至少得告诉别人我们都有什么,以及通过什么方法可以找到

吧!JMX技术给我们提供了一种手段。JMX里面主要有3种东西。Mbean,agent,connector.

Mbean:用来映射我们的对象。也许mbean就是我们创建的对象,也许不是,但有了它,就可以引用到我们的对象了。

Agent:

通过它,就可以找到mbean了。

Connector:连接Agent的方式。可以是http的,也可以是rmi的,还可以直接通过socket。

发生在tomcat装配过程中的事情:

GlobalResourcesLifecycleListener类的初始化会被触发:

protectedstaticRegistryregistry=MBeanUtils.createRegistry();

会运行