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


    在了解了tomcat 的一些基本组件之后,学习启动过程就更容易理解了,因为启动过程就是启动各个组件。

    目录

    • 启动顺序
    • Bootstrap类
    • Catalina类
    • StandardServer类和StandardService类
    • 总结

    启动顺序

    tomcat的启动主要是容器的启动,根据tomcat四层架构,启动时由上而下的,而service包含这些组件,service又包含在server里面,启动顺序如下:

    Bootstrap类

    整个tomcat程序的入口——main函数,主要作用就是找到CATALINA_HOME,实例化Catalina类,并调用load和start进行整个服务器的初始化和启动

    (上图中最后还有一个start调用,由于图太高了没有截)

    main函数中new出了Bootstrap实例,主要执行了以下方法

    • init:设置catalinaHome和catalinaBase(和catalinaHome一样)为bootstrap.jar的上一级目录,初始化tomcat的classLoader,获得Catalina的实例(后面load和start都调用了Catalina的方法)
    • setAwait:调用Catalina的setAwait设置服务器处于等待标志
    • load:调用Catalina的load方法进行服务器的初始化
    • start:调用Catalina的start方法启动服务器

    Catalina类

    主要作用是初始化并启动 StandardServer

    load

    load主要执行以下方法:

    • initDir:再次检查设置catalinaHome
    • initNaming:设置系统变量表明是否使用naming
    • createStartDigester:新建一个Digester解析server.xml,用来初始化StandardServer

    (最左边的是catalina)

    这里面最重要的就是createStartDigester方法(方法内部是添加一系列对应rule,要理解这个函数的实现要先去学习digest解析xml库),tomcat使用用来解析xml 的digest库,可以根据xml来生成对应的类并初始化:

    • digester.push(this):将catalina压在栈底(digester使用栈来解析xml),为了将StandardServer设置为catalina的变量(后面用到了StandardServer的init和start方法)
    • digester.parse():解析service.xml

    经过上面得到一个StandardServer的实例以后,调用StandardServer.init方法进行StandardServer的初始化。

    start

    start函数主要进行了以下操作:

    • 先判断getServer是否为null,若是则再次调用load进行初始化
    • 如果依然初始化失败则表明服务器初始化失败直接返回
    • getServer.start:调用StandardServer的start方法进行服务器初始化
    • 注册关闭服务器钩子(如果服务器没有正常关闭,该钩子可以进行关闭和清理工作)
    • 最后调用StandardServer的await方法监听端口等待关闭命令
    • 因为await方法是阻塞方法(等待socket),等await方法执行完成的时候(表明接收到shutdown命令)使用stop进行关闭服务器

    StandardServer类和StandardService类

    因为server和service联系紧密所以放到一块来说,server的主要任务是初始化并启动所有的service(如果有多个的话)

    StandardServer.init

    在catalina的load方法中调用了StandardServer的init方法,但是StandardServer没有重载超类LifeBase的init方法,所以是直接执行LifeBase.init方法

    最后会调用到StandardServer的initInternal方法,在该方法中进行了以下操作:

    • 调用父类LifecycleMBeanBase.initInternal方法进行注册MBean
    • 从低向上逐级验证tomcat类加载器
    • 使用循环逐个初始化service(在解析serverx.xml的时候已经实例化StandardService并调用StandardServer.addService()添加到StandardServer.services变量中),在标准server.xml配置中只有一个service——StandardService,所有就是只调用StandardService.init()

    StandardService.init

    最后也会调用到StandardService的initInternal方法,在该方法中进行了以下操作:

    • 调用父类LifecycleMBeanBase.initInternal方法进行注册MBeang
    • 如果container(这里的container是StandardEngine)不是null,则调用container的init方法进行初始化
    • 如果有Executor则逐个初始化
    • 最后使用循环逐个在初始化Connector,这里connector有两个,分别是用来处理两种协议:http和ajp

    StandardServer.start

    最后会调用StandardServe.startInternal,执行以下操作

    • 触发listener
    • 启动globalNamingResource
    • 启动所有service

    StandardService.start

    最后会调用到StandardService的startInternal,执行以下操作:

    • setState设置service的状态,并通知所有listener
    • 启动container
    • 启动executor
    • 启动connector(和初始化的时候一样)

    总结

    上一节说过StandardServer和StandardService的作用,但是经过这一节才更明白,service负责初始化并启动了container、executor和connector,所以接下来主要是分析StandardService如何启动container和connector。

  • 相关阅读:
    android视频录制
    UIWebView 缓存
    (Detected problems with API compatibility(visit g.co/dev/appcompat for more info)
    二、为什么要安装jdk?
    一、java为什么叫java?
    jstl标签
    J2EE(八)——myeclipse开发servlet
    J2EE(七)——myeclipse开发servlet
    J2EE(六)——servlet生命周期
    J2EE(五)——servlet初识
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/5745868.html
Copyright © 2020-2023  润新知