Tomcat启动过程源码分析

Tomcat启动过程分析

Tomcat默认server.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">  
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

Tomcat只是一个工具,为我们提供一个以war包方式运行web程序的环境而已

server.xml文件是Tomcat的核心文件之一

1.启动Bootstrap

volatile修饰是为了启动唯一的Bootstrap

public final class Bootstrap {
 	//volatile修饰的静态对象
    private static volatile Bootstrap daemon = null;
}

main()

创建Bootstrap对象,并通过初始命令"start"来启动Tomcat

//BootStrap.main()
if (daemon == null) {
	Bootstrap bootstrap = new Bootstrap();
    ......
    bootstrap.init();//通过反射创建Catalina对象
	......
	daemon = bootstrap;        
}
......
String command = "start";
......
daemon.start(); //通过反射调用Catalina的start方法

//Bootstrap.start()
public void start() throws Exception {
    if (catalinaDaemon == null) {
        init();//bootstrap的初始化
    }
    //反射执行Catalina的start方法,执行
    Method method = catalinaDaemon.getClass().getMethod("start", (Class[]) null);
    method.invoke(catalinaDaemon, (Object[]) null);
}

综上:

1.Tomcat的启动入口为Bootstrap的Main方法

2.在Main方法中生成Bootstrap对象,Catalina对象

2.Catalina是Tomcat的一个命令程序,Tomcat的启动与关闭就是对bootstrap和catalina对象的创建和销毁过程

2.启动Catalina

在上面Bootstrap的启动过程中会生成Catalina并通过反射调用Catalina的start方法

//Catalina.start()
public void start() {
	......
    if (getServer() == null) {
        load();//加载server.xml文件并创建server
    }
    //server的初始化
    getServer().start();
  	......
}

3. server.xml文件的加载与解析

在Catalina的start()方法中通过load()方法加载server.xml文件

//Catalina.load()
public void load() {
 	......
    parseServerXml(true); //加载并解析server.xml文件,会创建server,service等组件
    Server s = getServer();
    if (s == null) {
        return;
    }
	//server赋值
    getServer().setCatalina(this);
    getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
    getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
    ......
    // Start the new server
    try {
    	//server初始化
        getServer().init();
    } ......
}

server.xml文件的加载解析过程

protected void parseServerXml(boolean start) {
    ......

    if (serverXml != null) {
        serverXml.load(this);
    } else {
        try (ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getServerXml()) {
            // Create and execute our Digester
            Digester digester = start ? createStartDigester() : createStopDigester();
            InputStream inputStream = resource.getInputStream(); //server.xml流文件
            InputSource inputSource = new InputSource(resource.getURI().toURL().toString());
            inputSource.setByteStream(inputStream);
            digester.push(this);
            ......
        }
    }

创建Digester,设置规则,然后进行解析

在server.xml的解析过程中会创建server,service等组件

protected Digester createStartDigester() {
    // Initialize the digester
    Digester digester = new Digester();
    digester.setValidating(false);
    digester.setRulesValidation(true);
    Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
    // Ignore className on all elements
    List<String> objectAttrs = new ArrayList<>();
    objectAttrs.add("className");
    fakeAttributes.put(Object.class, objectAttrs);
    // Ignore attribute added by Eclipse for its internal tracking
    List<String> contextAttrs = new ArrayList<>();
    contextAttrs.add("source");
    fakeAttributes.put(StandardContext.class, contextAttrs);
    // Ignore Connector attribute used internally but set on Server
    List<String> connectorAttrs = new ArrayList<>();
    connectorAttrs.add("portOffset");
    fakeAttributes.put(Connector.class, connectorAttrs);
    digester.setFakeAttributes(fakeAttributes);
    digester.setUseContextClassLoader(true);

    //创建server
    digester.addObjectCreate("Server",
                             "org.apache.catalina.core.StandardServer",
                             "className");
    digester.addSetProperties("Server");
    digester.addSetNext("Server",
                        "setServer",
                        "org.apache.catalina.Server");
	//全局命名
    digester.addObjectCreate("Server/GlobalNamingResources",
                             "org.apache.catalina.deploy.NamingResourcesImpl");
    digester.addSetProperties("Server/GlobalNamingResources");
    digester.addSetNext("Server/GlobalNamingResources",
                        "setGlobalNamingResources",
                        "org.apache.catalina.deploy.NamingResourcesImpl");
	//server生命周期监听器
    digester.addRule("Server/Listener",
                     new ListenerCreateRule(null, "className"));
    digester.addSetProperties("Server/Listener");
    digester.addSetNext("Server/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");
	//创建service,在server组件中添加service属性
    digester.addObjectCreate("Server/Service",
                             "org.apache.catalina.core.StandardService",
                             "className");
    digester.addSetProperties("Server/Service");
    digester.addSetNext("Server/Service",
                        "addService",
                        "org.apache.catalina.Service");
	//为service添加监听器
    digester.addObjectCreate("Server/Service/Listener",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Listener");
    digester.addSetNext("Server/Service/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");

    //Executor,共享executor的级别为service,默认情况下不开启
    digester.addObjectCreate("Server/Service/Executor",
                             "org.apache.catalina.core.StandardThreadExecutor",
                             "className");
    digester.addSetProperties("Server/Service/Executor");

    digester.addSetNext("Server/Service/Executor",
                        "addExecutor",
                        "org.apache.catalina.Executor");

    digester.addRule("Server/Service/Connector",
                     new ConnectorCreateRule());
    digester.addSetProperties("Server/Service/Connector",
                              new String[]{"executor", "sslImplementationName", "protocol"});
    digester.addSetNext("Server/Service/Connector",
                        "addConnector",
                        "org.apache.catalina.connector.Connector");

    digester.addRule("Server/Service/Connector", new AddPortOffsetRule());

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
                             "org.apache.tomcat.util.net.SSLHostConfig");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig",
                        "addSslHostConfig",
                        "org.apache.tomcat.util.net.SSLHostConfig");

    digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
                     new CertificateCreateRule());
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig/Certificate", new String[]{"type"});
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
                        "addCertificate",
                        "org.apache.tomcat.util.net.SSLHostConfigCertificate");

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
                             "org.apache.tomcat.util.net.openssl.OpenSSLConf");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
                        "setOpenSslConf",
                        "org.apache.tomcat.util.net.openssl.OpenSSLConf");

    digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
                             "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
    digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
    digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
                        "addCmd",
                        "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");

    digester.addObjectCreate("Server/Service/Connector/Listener",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Connector/Listener");
    digester.addSetNext("Server/Service/Connector/Listener",
                        "addLifecycleListener",
                        "org.apache.catalina.LifecycleListener");

    digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
                             null, // MUST be specified in the element
                             "className");
    digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
    digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
                        "addUpgradeProtocol",
                        "org.apache.coyote.UpgradeProtocol");

    // Add RuleSets for nested elements
    digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
    digester.addRuleSet(new EngineRuleSet("Server/Service/"));
    digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
    digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
    addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
    digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));

    // When the 'engine' is found, set the parentClassLoader.
    digester.addRule("Server/Service/Engine",
                     new SetParentClassLoaderRule(parentClassLoader));
    addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");

    return digester;

}

4.启动Server

解析server.xml文件过程中根据规则创建server组件,为Server组件添加Service组件

//StandardServer.addService()
@Override
public void addService(Service service) {
    service.setServer(this);
    synchronized (servicesLock) {
        Service results[] = new Service[services.length + 1];
        System.arraycopy(services, 0, results, 0, services.length);
        results[services.length] = service;
        services = results;
        ......
            service.start(); //启动service
       	......

5.启动Service

通过生命周期方法start()---->startInternal() 初始化组件

//standardService
protected void startInternal() throws LifecycleException {

    if(log.isInfoEnabled())
        log.info(sm.getString("standardService.start.name", this.name));
    setState(LifecycleState.STARTING);

    //初始化engine
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }
	//初始化executor
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }
	//启动mapperLinstener
    mapperListener.start();

   	//启动connectors
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            // If it has already failed, don't try and start it
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}

service组件在初始化过程中会初始化engin,Executor,Connector等组件,这些组件都是在解析server.xml文件时添加的

6.Engine

7.启动Connector

Connector是Tomcat的连接器,默认使用Http协议

public class Connector extends LifecycleMBeanBase  {
 	//默认http1.1协议
    public Connector() {
        this("org.apache.coyote.http11.Http11NioProtocol");
    }
    ......
    public Connector(String protocol) {
    	......
        ProtocolHandler p = null;
        try {
            p = ProtocolHandler.create(protocol, apr);//创建protocolhandler
        ......
    }
}

startInternal()

启动protocolHandler

try {
    protocolHandler.start();
} 

8. 启动ProtocolHandler

ProtocolHandler是负责处理请求的,一般情况下处理Http请求,因此默认使用Http协议

AbstractProtocol

public abstract class AbstractProtocol<S> implements ProtocolHandler,
        MBeanRegistration {
    //处理请求之前需要先监听请求,Endpoint负责绑定请求并进行监听
    private final AbstractEndpoint<S,?> endpoint;
    
    //构造方法
    public AbstractHttp11Protocol(AbstractEndpoint<S,?> endpoint) {
        super(endpoint);
        setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
        ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
        setHandler(cHandler);
        //NioEndpoint设置protocelHandler
        getEndpoint().setHandler(cHandler);
    }

protocolHandler.start()

protocolHandler通过endpoint监听http请求,初始endpoint

//AbstractProtocol.start()
public void start() throws Exception {
    if (getLog().isInfoEnabled()) {
        getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
        logPortOffset();
    }
	//初始化endPoint
    endpoint.start();
    monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
        new Runnable() {
            @Override
            public void run() {
                if (!isPaused()) {
                    startAsyncTimeout();
                }
            }
        }, 0, 60, TimeUnit.SECONDS);
}

9.AbstractEndpoint

Endpoint负责监听Socket,在监听之前先初始化并进行与socket绑定

start()

public final void start() throws Exception {
    if (bindState == BindState.UNBOUND) {//未绑定状态
        bindWithCleanup();
        bindState = BindState.BOUND_ON_START;
    }
    startInternal();//初始化操作,由具体子类实现
}

10. 启动NioEndpoint

此处有三个组件:分别是Poller,PollerEvent,Acceptor

启动NioEndpoint,设置最大连接数,开启线程监听socket等

//NioEndpoint
@Override
public void startInternal() throws Exception {

    if (!running) {
        running = true;
        paused = false;

        ......

        // Create worker collection
        if (getExecutor() == null) {
            createExecutor();
        }
        //设置最大连接数
        initializeConnectionLatch();

        //初始化Poller并开启线程监听事件队列
        poller = new Poller();
        Thread pollerThread = new Thread(poller, getName() + "-ClientPoller");
        pollerThread.setPriority(threadPriority);
        pollerThread.setDaemon(true);
        pollerThread.start();
        //启动Acceptor
        startAcceptorThread();
    }
}

11.启动Acceptor

开启Acceptor线程来监听socket

//AbstractEndpoint
protected void startAcceptorThread() {
    acceptor = new Acceptor<>(this);
    String threadName = getName() + "-Acceptor";
    acceptor.setThreadName(threadName);
    Thread t = new Thread(acceptor, threadName);
    t.setPriority(getAcceptorThreadPriority());
    t.setDaemon(getDaemon());
    t.start();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值