您的位置:首页 > 运维架构 > Tomcat

TOMCAT源码分析(启动框架)

2011-10-12 12:51 483 查看
转载于:http://doc.linuxpk.com/46823.html

 前言:

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

  建议:

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

  1. Tomcat的整体框架结构

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

  Top Level Elements:

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

  Container: 当http connector把需求传递给顶级的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的意思其实就是一个web app的意思。

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

  

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

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

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

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

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

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

  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.3 Catalina.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 类的初始化会被触发:

  protected static Registry registry = MBeanUtils.createRegistry();

  会运行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: