当前位置:   article > 正文

Tomcat -- 启动流程_tomcat启动流程

tomcat启动流程

web概念

  1. 软件架构
    a. C/S:客户端、服务器端架构,如微信,QQ
    b. B/S:浏览器、服务器端架构,如淘宝等门户网站
  2. 资源类别
    a. 静态资源:所有用户访问得到的结果都一样,称为静态资源,可以直接被浏览器解析,如html、css、jpg等
    b. 动态资源:每个用户访问得到的结果可能不一致,动态资源被访问后需要先转换为静态资源,再返回给浏览器,由浏览器解析,如:jsp、servlet等
  3. 网络三要素
    a. ip:电子设备在网络的唯一标识
    b. 端口:应用程序在计算机中的唯一标识
    c. 传输协议:规定数据传输的规则

tomcat启动原理

  • 加载tomcat配置文件,初始化容器组件,监听对应的端口号,准备接受客户端请求
    在这里插入图片描述
启动流程
  • 启动tomcat,执行bin/startup.bat脚本,调用catalina.bat脚本
  • 执行调用BootStrap中main方法,调用init方法,通过反射创建Catalina对象及初始化类加载器
  • main方法中调用load方法,会调用Catalina的load方法
  • Catalina的load方法会进行Server中的一系列主键的初始化工作,并构造Digester对象,负责解析XML
  • 加载tomcat配置文件,初始化容器组件,监听对应的端口号,准备接受客户端请求
启动源码

生命周期方法(Lifecycle)

  • 所有组件都存在初始化、启动、停止等生命周期方法,tomcat基于生命周期管理抽象成Lifecycle接口
  • 组件Server、Service、Container、Executor、Connector都实现Lifecycle,通过Lifecycle统一管理个组件的生命周期接口
    ○ init:初始化组件接口
    ○ start:启动组件接口
    ○ stop:停止组件接口
    ○ destroy:销毁组件接口

组件默认实现
在这里插入图片描述

源码跟踪

在这里插入图片描述

startup.bat 启动文件
:okHome
//调用catalina.bat 
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"

rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec

rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs
//执行
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
:end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
catalina.bat (bootstrap.jar)
if "%CLASSPATH%" == "" goto emptyClasspath
set "CLASSPATH=%CLASSPATH%;"
:emptyClasspath
set "CLASSPATH=%CLASSPATH%%CATALINA_HOME%\bin\bootstrap.jar"
  • 1
  • 2
  • 3
  • 4
启动入口 Bootstrap.main

org.apache.catalina.startup.Bootstrap#main

public static void main(String args[]) {
    synchronized (daemonLock) {
        //执行init方法初始化,创建Catalina对象
        bootstrap.init();
        //...
        String command = "start";
        //...
        if (command.equals("startd")) {
            args[args.length - 1] = "start";
            daemon.load(args);
            daemon.start();
        } else if (command.equals("stopd")) {
            args[args.length - 1] = "stop";
            daemon.stop();
        } else if (command.equals("start")) {
            daemon.setAwait(true);
            daemon.load(args);
            daemon.start();
            if (null == daemon.getServer()) {
                System.exit(1);
            }
        } else if (command.equals("stop")) {
            daemon.stopServer(args);
        } else if (command.equals("configtest")) {
            daemon.load(args);
            if (null == daemon.getServer()) {
                System.exit(1);
            }
            System.exit(0);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
Bootstrap初始化组件

解析配置xml :org.apache.catalina.startup.Catalina#parseServerXml

初始化Bootstrap – bootstrap.init
  • 初始化ClassLoader
  • 通过反射创建Catalina(反射解耦)
public void init() throws Exception {
    //初始化ClassLoader
    initClassLoaders();
    Thread.currentThread().setContextClassLoader(catalinaLoader);
    SecurityClassLoad.securityClassLoad(catalinaLoader);
	//使用自定义ClassLoader类加载器 反射创建Catalina
    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
    Object startupInstance = startupClass.getConstructor().newInstance();
    String methodName = "setParentClassLoader";
    Class<?> paramTypes[] = new Class[1];
    paramTypes[0] = Class.forName("java.lang.ClassLoader");
    Object paramValues[] = new Object[1];
    paramValues[0] = sharedLoader;
    //反射获取Catalina的setParentClassLoader
    Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
    //设置父ClassLoader
    method.invoke(startupInstance, paramValues);
    catalinaDaemon = startupInstance;
}

因为Bootstrap这个类在Tomcat打包发布时是放在bin\bootstrap.jar中,
而Catalina类是放在lib\catalina.jar中,两个jar是用不同的ClassLoader加载的,
所以不能在Bootstrap类中直接引用Catalina类,只能通过反射。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
加载Bootstrap – daemon.load(args)
  • 执行Bootstrap的load方法
  • 反射调用Catalina的load方法
private void load(String[] arguments) throws Exception {
    String methodName = "load";
    //....
    //获取Catalina的load方法
    Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes);
    //通过反射调用Catalina.load方法
    method.invoke(catalinaDaemon, param);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
加载Catalina – Catalina.load
  • 执行初始化
  • 解析server.xml配置文件–parseServerXml
    – 创建启动或者停止的xml解析器Digester
  • 创建Server
  • 初始化Server
public void load() {
    //执行初始化
    initDirs();
    initNaming();
    //解析server.xml配置文件
    parseServerXml(true);
    //创建Server
    Server s = getServer();
    //初始化Server
    getServer().init();
}

// 解析server.xml
protected void parseServerXml(boolean start) {
    //....
    try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()) {
        //创建启动或者停止的xml解析器Digester
        Digester digester = start ? createStartDigester() : createStopDigester();
        //....
    } catch (Exception e) {
        log.warn(sm.getString("catalina.configFail", file.getAbsolutePath()), e);
        if (file.exists() && !file.canRead()) {
            log.warn(sm.getString("catalina.incorrectPermissions"));
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
初始化Server – Lifecycle.init()
  • 调用抽象方法,执行具体实现,初始化
  • 模板方法模式
  • 执行实现的StandardServer.initInternal方法初始化Server
  • 循环初始化Service
public final synchronized void init() throws LifecycleException {
    if (!state.equals(LifecycleState.NEW)) {
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }
    try {
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        //调用抽象方法,执行具体实现,初始化
        initInternal();
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    } catch (Throwable t) {
        handleSubClassException(t, "lifecycleBase.initFail", toString());
    }
}

protected void initInternal() throws LifecycleException {
    super.initInternal();
    //初始化
    reconfigureUtilityExecutor(getUtilityThreadsInternal(utilityThreads));
    register(utilityExecutor, "type=UtilityExecutor");
    onameStringCache = register(new StringCache(), "type=StringCache");
    // Register the MBeanFactory
    MBeanFactory factory = new MBeanFactory();
    factory.setContainer(this);
    onameMBeanFactory = register(factory, "type=MBeanFactory");
    globalNamingResources.init();

    //循环初始化Service
    for (Service service : services) {
        service.init();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
初始化Service – service.init
  • 同初始化Server,模板方法调用 Lifecycle.init()
  • 调用StandardService.initInternal方法
  • 初始化Engine引擎
  • 初始化Executor线程连接池
    ○ tomcat线程池与jdk线程池区别
    ○ tomcat自定义TaskQueue, 默认队列大小是无限大队列,
    ○ tomcat重写了offer入队方法,
    ○ 如果线程池线程数量小于线程池最大线程池,则入队失败(会直接开启非核心线程接收请求,而非入队)
  • 初始化监听器
  • 初始化Connector连接器
protected void initInternal() throws LifecycleException {
    super.initInternal();
	//初始化Engine引擎
    if (engine != null) {
        engine.init();
    }
    //初始化Executor线程池
    for (Executor executor : findExecutors()) {
        if (executor instanceof JmxEnabled) {
            ((JmxEnabled) executor).setDomain(getDomain());
        }
        executor.init();
    }
    // 初始化监听器
    mapperListener.init();
    //初始化Connector连接器
    synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            connector.init();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
初始化Connector – Connector.initInternal
  • 初始化CoyoteAdapter适配器
  • 初始化ProtocolHandler
protected void initInternal() throws LifecycleException {
    // 初始化CoyoteAdapter
    adapter = new CoyoteAdapter(this);
    protocolHandler.setAdapter(adapter);
	//....
    //初始化ProtocolHandler
    protocolHandler.init();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
初始化ProtocolHandler
  • 初始化EndPoint
public void init() throws Exception {
    //....
    String endpointName = getName();
    endpoint.setName(endpointName.substring(1, endpointName.length()-1));
    endpoint.setDomain(domain);
	//初始化EndPoint
    endpoint.init();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
初始化EndPoint – AbstractEndpoint.init
  • 绑定Servlet
  • 注册EndPoint
public final void init() throws Exception {
    if (bindOnInit) {
        //绑定Servlet相关能力
        bindWithCleanup();
        bindState = BindState.BOUND_ON_INIT;
    }
    if (this.domain != null) {
        // 注册EndPoint
        oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
        Registry.getRegistry(null, null).registerComponent(this, oname, null);
        ObjectName socketPropertiesOname = new ObjectName(domain + ":type=SocketProperties,name=\"" + getName() + "\"");
        socketProperties.setObjectName(socketPropertiesOname);
        Registry.getRegistry(null, null).registerComponent(socketProperties, socketPropertiesOname, null);
        for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
            registerJmx(sslHostConfig);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
绑定Servlet
  • 初始化ServerSocket
  • 初始化SSL
public void bind() throws Exception {
    //初始化ServerSocket
    initServerSocket();

    setStopLatch(new CountDownLatch(1));

    //初始化SSL
    initialiseSsl();

    selectorPool.open(getName());
}

//初始化ServerSocket
protected void initServerSocket() throws Exception {
    if (!getUseInheritedChannel()) {
        serverSock = ServerSocketChannel.open();
        socketProperties.setProperties(serverSock.socket());
        InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
        serverSock.socket().bind(addr,getAcceptCount());
    } else {
        Channel ic = System.inheritedChannel();
        if (ic instanceof ServerSocketChannel) {
            serverSock = (ServerSocketChannel) ic;
        }
        if (serverSock == null) {
            throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
        }
    }
    serverSock.configureBlocking(true); //mimic APR behavior
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
Bootstrap启动
启动Bootstrap – bootstrap.start
  • 如果没有初始化,则在此初始化
  • 反射调用Catalina的start方法
public void start() throws Exception {
    //如果没有初始化,则在此初始化
    if (catalinaDaemon == null) {
        init();
    }
	//反射调用Catalina的start方法
    Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
    method.invoke(catalinaDaemon, (Object [])null);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
启动Catalina.start
  • 启动Server
  • 启动失败则销毁Server
public void start() {
    //启动Server
    try {
        getServer().start();
    } catch (LifecycleException e) {
        try {
            //启动失败则销毁
            getServer().destroy();
        } catch (LifecycleException e1) {
            log.debug("destroy() failed for failed Server ", e1);
        }
        return;
    }

    if (generateCode) {
        // Generate loader which will load all generated classes
        generateLoader();
    }

    // Register shutdown hook
    if (useShutdownHook) {
        if (shutdownHook == null) {
            shutdownHook = new CatalinaShutdownHook();
        }
        Runtime.getRuntime().addShutdownHook(shutdownHook);

        LogManager logManager = LogManager.getLogManager();
        if (logManager instanceof ClassLoaderLogManager) {
            ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                false);
        }
    }

    if (await) {
        await();
        stop();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
启动Server – Lifecycle.start
  • 调用抽象方法,执行具体实现,初始化
  • 模板方法模式
  • 执行实现的StandardServer.startInternal方法启动Server
  • 循环启动Service

public final synchronized void start() throws LifecycleException {
	//....
    setStateInternal(LifecycleState.STARTING_PREP, null, false);
    //
    startInternal();

}

protected void startInternal() throws LifecycleException {

    //循环启动service
    synchronized (servicesLock) {
        for (Service service : services) {
            service.start();
        }
    }

    if (periodicEventDelay > 0) {
        monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
            new Runnable() {
                @Override
                public void run() {
                    startPeriodicLifecycleEvent();
                }
            }, 0, 60, TimeUnit.SECONDS);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
启动Service – StandardService.startInternal
  • 启动Engine引擎
  • 启动Executor线程连接池
  • 启动监听器
  • 启动Connector连接器
protected void startInternal() throws LifecycleException {
    // 启动Engine引擎
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }
	//启动Executor线程连接池
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }
	//启动监听器
    mapperListener.start();
    //启动Connector连接器
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
启动Connector – Connector.startInternal
  • 设置状态
  • 启动ProtocolHandler
protected void startInternal() throws LifecycleException {
	//设置状态
    setState(LifecycleState.STARTING);
	//启动ProtocolHandler
    protocolHandler.start();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
启动ProtocolHandler – AbstractProtocol.start
public void start() throws Exception {
    //启动Endpoint
    endpoint.start();
    monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
        new Runnable() {
            @Override
            public void run() {
                if (!isPaused()) {
                    startAsyncTimeout();
                }
            }
        }, 0, 60, TimeUnit.SECONDS);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
启动Endpoint
  • 初始化连接
  • 启动接收的线程
public final void start() throws Exception {
    if (bindState == BindState.UNBOUND) {
        bindWithCleanup();
        bindState = BindState.BOUND_ON_START;
    }
    startInternal();
}

public void startInternal() throws Exception {
	//初始化连接
    initializeConnectionLatch();
    //启动接收的线程
    startAcceptorThread();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
Acceptor接收器 – socket.accept
  • 实现Runnable
  • run方法接收客户端请求
  • socket.accept监听接收客户端请求
public class Acceptor<U> implements Runnable {
    @Override
    public void run() {
        //接收客户端请求
        socket = endpoint.serverSocketAccept();
    }
}
//socket.accept监听接收客户端请求
protected SocketChannel serverSocketAccept() throws Exception {
    return serverSock.accept();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

参考资源: Java进阶教程Tomcat核心原理解析

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/算法编织者/article/detail/61536
推荐阅读
相关标签
  

闽ICP备14008679号