How Tomcat works — 四、tomcat启动(3)

上一节说到StandardService负责启动其子组件:container和connector,不过注意,是有先后顺序的,先启动container,再启动connector,这一节先来看看container。

目录

  • Pipeline和Vavle
  • StandardEngine类和StandardHost类
  • StandardContext类
  • 总结

Pipeline和Vavle

在第二节(How Tomcat works — 二、tomcat启动(1))中没有介绍关于Pipeline和Vavle,因为前面侧重的是整个架构,但是在初始化的时候就不得不说了。

Pipeline,就是一根管道,用来连接两个容器,在一个容器流向下一个容器的时候使用。在tomcat中也是这个意思,很形象,Engine、Host等都是容器,在执行完上一个容器(比如Engine)的相关操作的时候要开始执行下一个容器(比如Host)的操作了,这个时候需要经过一根管道pipeline,那么我们可以在管道中执行一个其他必要的操作,这个时候可以在管道上面添加Vavle(阀),一根管道pipeline上可以有多个阀门(也很形象)。每根管道都有一个默认的阀门。

在tomcat实现中有一个实现了Pipeline接口的类StandardPipeline——是每两个容器之间的管道,每个容器都有一个默认的Valve实现StandardEnginevavle、StandardHostValve、StandardContextVavle、StandardWrapperVavle。

其实valve的作用和filter的作用类似。

StandardEngine类

StandardEngine作为整个容器的最顶层负责启动其子组件——StandardHost,对,他就这一个作用。

StandardEngine.initInternal

这个方法被超类LifecycleBase.init方法调用,主要作用就是调用超类LifecycleMBeanBase.initInternal方法注册MBean,并初始化一个startStopExecutor(ThreadPoolExecutor),后面用来使用线程启动子容器。

StandardEngine.startInternal

这个方法的主要作用就是调用父类的方法Container.startInternal——主要的操作就在这个方法里面:

protected synchronized void startInternal() throws LifecycleException {

    // Start our subordinate components, if any
    if ((loader != null) && (loader instanceof Lifecycle))
        ((Lifecycle) loader).start();
    logger = null;
    getLogger();
    if ((manager != null) && (manager instanceof Lifecycle))
        ((Lifecycle) manager).start();
    if ((cluster != null) && (cluster instanceof Lifecycle))
        ((Lifecycle) cluster).start();
    Realm realm = getRealmInternal();
    if ((realm != null) && (realm instanceof Lifecycle))
        ((Lifecycle) realm).start();
    if ((resources != null) && (resources instanceof Lifecycle))
        ((Lifecycle) resources).start();

    // Start our child containers, if any
    Container children[] = findChildren();
    List<Future<Void>> results = new ArrayList<Future<Void>>();
    for (int i = 0; i < children.length; i++) {
        results.add(startStopExecutor.submit(new StartChild(children[i])));
    }

    boolean fail = false;
    for (Future<Void> result : results) {
        try {
            result.get();
        } catch (Exception e) {
            log.error(sm.getString("containerBase.threadedStartFailed"), e);
            fail = true;
        }

    }
    if (fail) {
        throw new LifecycleException(
                sm.getString("containerBase.threadedStartFailed"));
    }

    // Start the Valves in our pipeline (including the basic), if any
    if (pipeline instanceof Lifecycle)
        ((Lifecycle) pipeline).start();

    setState(LifecycleState.STARTING);

    // Start our thread
    threadStart();

}

  • manager、cluster、realm、resource如果有的话全部启动(所以其实tomcat本身就是支持集群的)
  • 调用findChildren方法找到左右子容器——也就是所有的StandardHost(默认只有一个)
  • 对于每个子容器(StandardHost)使用线程启动,StartChild类实现了Callable接口,在call方法里面执行传入容器的start方法,将子容器启动作为一个task,然后使用ThreadPoolExecutor.submit提交task
  • 然后等待这些Future执行完(因为里面是各个子容器的初始化和启动工作,后面connector必须在容器准备好之后才能启动)
  • 启动pipeline(这里就是StandardPipeline),pipeline会启动所包含的所有vavle(这里就是只有StandardEngineValve)
  • setState会通知所有监听了StandardEngine事件的listener
  • threadStart,启动一个后台线程执行包含的所有阀门的backgroundProcess方法,并触发Lifecycle.PERIODIC_EVENT事件

StandardHost类

StandardHost的作用和StandardEngine类似,都是初始化启动子容器,不过这里是StandardContext。启动的方式也一样,所以就不再详述。

StandardContext类

这个类才是重中之重,解析web.xml、部署webapp都在这儿实现。在StandardHost中调用StandardContext.start方法,执行的是超类LifecycleBase.start方法,主要进行了如下操作

  • 调用init方法初始化StandardContext
  • 调用startInternal方法启动StandardContext

init

在该方法中主要进行了MBean的注册,再就是触发了Lifecycle.AFTER_INITEVENT事件,ContextConfig是StandardContext的listener,在发生该事件的时候执行ContextConfig.init方法,在该方法中主要是构造一个能解析web.xml的digester。

startInternal

由于LifecycleBase没有实现该方法,所以就是直接调用StandardContext.startInternal,在StandardContext.startInternal方法中主要进行了如下操作:

  • setResource:添加新的resource
  • 如果webappLoader为null则初始化
  • 初始化charset mapper
  • 设置webapp工作目录,比如%TOMCAT_HOME%/work//Catalina/localhost/_等
  • 触发Lifecycle.CONFIGURE_START_EVENT事件,ContextConfig监听了该事件,会进行解析web.xml
  • 启动所有的children(StandardWrapper,代表所有配置的servlet)
  • 初始化Standardmanager
  • 配置initParam
  • 配置启动filter、listener

总结

container部分终于启动完成了,不过还是有些部分略过了,比如StandardWrapper(这个还可以往深挖,不过也包含在StandardContext的启动过程中)初始化和webapp的发布。到现在发现,这些启动过程就是围绕生命周期的这几个方法展开:

  • start和init:LifecycleBase提供了默认实现
  • startInternal和initInternal:这两个方法每个类都是重载实现自己需要启动的东西
时间: 2024-12-28 06:54:24

How Tomcat works — 四、tomcat启动(3)的相关文章

how tomcat works 读书笔记四 tomcat的默认连接器

其实在第三章,就已经有了连接器的样子了,不过那只是一个学习工具,在这一章我们会开始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足以下几个要求 1 实现org.apache.cataline.Connector接口 2 负责创建实现了org.apache.cataline.Request接口的request对象 3 负责创建实现了org.apache.cataline.Response接口的response对象 这里默认的连接器的原理很简单,就是等待http请求,创建re

How Tomcat works — 二、tomcat启动(1)

主要介绍tomcat启动涉及到的一些接口和类. 目录 概述 tomcat包含的组件 Lifecycle Container Connector 总结 概述 tomcat作为一个服务器,它的主要功能就是接收请求——处理请求——返回,如果是我们自己实现一个最简单的服务器,启动一个线程监听某个端口,该端口有数据进来的话就接收数据,然后在启动一个线程去处理接收到的数据并返回.那么启动一个服务器最重要的就是启动一个线程监听某个端口,tomcat也是,只不过tomcat包含很多组件,首先要完成组件的初始化,

How Tomcat works — 三、tomcat启动(2)

在了解了tomcat 的一些基本组件之后,学习启动过程就更容易理解了,因为启动过程就是启动各个组件. 目录 启动顺序 Bootstrap类 Catalina类 StandardServer类和StandardService类 总结 启动顺序 tomcat的启动主要是容器的启动,根据tomcat四层架构,启动时由上而下的,而service包含这些组件,service又包含在server里面,启动顺序如下: Bootstrap类 整个tomcat程序的入口——main函数,主要作用就是找到CATAL

Tomcat:解决Tomcat可以在eclipse启动,却无法显示默认页面的操作

解决Tomcat可以在eclipse启动,却无法显示默认页面的操作 今天在eclipse中配置好tomcat后访问不到它的主页,但是能运行自己的项目,一直找不到原因,百度之后最后解决了这个问题,总结如下: 原因在于eclipse是调用Tomcat的接口模拟tomcat而不是真正的启动它,因此显示不了Tomcat主页 解决办法如下: 一:双击控制台的Tomcat,如图所示: 二:修改以下两个地方: 三:若上图的单选框修改不了,如图所示: 那么最简单的解决办法就是:右击控制台的Tomcat选dele

《How Tomcat Works》读书笔记(二)

<How Tomcat Works>读书笔记(二) 这是<How Tomcat Works>第一二章的读书笔记.第一张主要写了一个静态资源处理的web服务器,第二章加了对servlet的处理. 1. 概述 1.1 架构 HttpServer:表示Http服务器,与客户端通信,处理Http请求. StaticResourceProcessor:对静态资源请求进行处理. ServletProcessor:对Servlet资源请求进行处理. Request:表示Http请求,实现了Ser

Tomcat的四种web应用部署方式详解

在Tomcat中有四种部署Web应用的方式,简要的概括分别是: (1)利用Tomcat自动部署 (2)利用控制台进行部署 (3)增加自定义的Web部署文件(%Tomcat_Home%\conf\Catalina\localhost\AppName.xml) (4)手动修改%Tomcat_Home%\conf\server.xml文件来部署web应用 第一种方式:利用Tomcat自动部署 利用Tomcat自动部署方式是最简单的.最常用的方式.若一个web应用结构为D:\workspace\WebA

how tomcat works

目标 深入剖析tomcat •Java Web 服务性能优化实践2014-11-04阅读225 •How Tomcat work之第十五章之Digester之setting property2014-07-30阅读253 •How Tomcat work 之第十四章之server and services 之application2014-07-29阅读194 •how tomcat work之第十四章:server and service2014-07-27阅读352 •How Tomcat

CentOS 64-bit下安装JDK和Tomcat并设置Tomcat开机启动操作步骤

准备文件如下: 1.CentOS-6.4-x86_64-bin-DVD1.iso 2.jdk-7u67-linux-x64.rpm 3.apache-tomcat-7.0.55.tar.gz 安装步骤如下: 一.安装JDK [[email protected] /]# java -versionbash: java: command not found [[email protected] /]# rpm -ivh /soft/jdk-7u67-linux-x64.rpmPreparing...

How Tomcat Works 2

上一节(How Tomcat Works 1 编写一个简单静态web服务器)编写了一个简单的web服务器,只能处理静态的资源,本节将继续向前迈出一个小步,创建两个不同的servlet容器,能够利用servlet简单的处理动态内容.注意每节的代码都是基于上一节的继续丰富,因此有必要从第一节开始看起. 在编写代码之前,需要先大体了解一下Servlet是什么,方便后面的理解,下面就是一个最简单的Servlet什么也没做: package prymont; import java.io.IOExcept