上一篇咱们看了Tomcat中各个组件的init过程,初始化赋值好了,那么接下来就该轮到start了,话不多说,马上进入主题~

1. Bootstrap.start()

通过start办法咱们能够看到他是通过反射调用了 Catalina.start() 办法,按F7跳到这个类外面看一下。

public void start() throws Exception {    if (catalinaDaemon == null) {        init();    }    // 通过反射调用 Catalina.start() 办法    Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);    method.invoke(catalinaDaemon, (Object [])null);}

2. Catalina.start()

进来一看,又是相熟的套娃格调,还得持续往里面跳转

3. LifecycleBase.start()

还是这个相熟的组件生命周期类,看到这里就好像看到了终局,必定是跟initInternal这个办法一样一层层嵌套进去,让咱们走起~

4. StandardServer.startInternal()

之前咱们有所过在一个Tomcat中是能够有多个service的,所以这里须要遍历所有的service别离让各自启动起来

server.xml文件中再给他配置一个<Service>标签即可,如图所示:

5. StandardService.startInternal()

开始进入正题了,在这个办法中咱们能够看到它别离做了以下操作:

  1. 容器的启动:engine.start()
  2. 连接器的启动:connector.start()
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 子容器            engine.start();        }    }    synchronized (executors) {        for (Executor executor: executors) {            executor.start();        }    }    mapperListener.start();    // Start our defined Connectors second    synchronized (connectorsLock) {        for (Connector connector: connectors) {            try {                // If it has already failed, don't try and start it                if (connector.getState() != LifecycleState.FAILED) {                    // 启动连接器                    connector.start();                }            } catch (Exception e) {                log.error(sm.getString(                    "standardService.connector.startFailed",                    connector), e);            }        }    }}

6. StandardEngine.startInternal()

这里间接调用的ContainerBase.startInternal办法实现上司组件的启动

protected synchronized void startInternal() throws LifecycleException {    // Log our server identification information    if(log.isInfoEnabled())        log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());    // Standard container startup    super.startInternal();}

7. ContainerBase.startInternal()

这里应用的是线程池的形式,如果有多个Host,那么就能够多个线程并行实例化Host,放慢Tomcat启动速度

protected synchronized void startInternal() throws LifecycleException {    // 启动上司容器    logger = null;    getLogger();    Cluster cluster = getClusterInternal();    if (cluster instanceof Lifecycle) {        ((Lifecycle) cluster).start();    }    Realm realm = getRealmInternal();    if (realm instanceof Lifecycle) {        ((Lifecycle) realm).start();    }    // 查找并启动子容器,Host 在初始化阶段后还是不残缺的,须要持续封装,把容器关系保护残缺    Container children[] = findChildren();    List<Future<Void>> results = new ArrayList<>();    for (Container child : children) {        results.add(startStopExecutor.submit(new StartChild(child)));    }    MultiThrowable multiThrowable = null;    for (Future<Void> result : results) {        try {            result.get();        } catch (Throwable e) {            log.error(sm.getString("containerBase.threadedStartFailed"), e);            if (multiThrowable == null) {                multiThrowable = new MultiThrowable();            }            multiThrowable.add(e);        }    }    if (multiThrowable != null) {        throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),                                     multiThrowable.getThrowable());    }    // 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();}

[图片上传失败...(image-bc6c2d-1616772543941)]

8. StandardHost.startInternal()

protected synchronized void startInternal() throws LifecycleException {    // Set error report valve    String errorValve = getErrorReportValveClass();    if ((errorValve != null) && (!errorValve.equals(""))) {        try {            boolean found = false;            Valve[] valves = getPipeline().getValves();            for (Valve valve : valves) {                if (errorValve.equals(valve.getClass().getName())) {                    found = true;                    break;                }            }            if(!found) {                Valve valve =                    (Valve) Class.forName(errorValve).getConstructor().newInstance();                getPipeline().addValve(valve);            }        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            log.error(sm.getString(                    "standardHost.invalidErrorReportValveClass",                    errorValve), t);        }    }    super.startInternal();}

Host的实例化,是通过设置生命周期状态来进行促发生命周期事件fireLifecycleEvent来执行后续工作的。

  1. deployApps:解决 host下多个利用
  2. deployDirectories:解决host上面以目录形式部署的(results.add(),这里也是以多线程的形式并行执行的)
  3. host.addChild():这时猜触发context实例核心内容
  4. context:具体读取web.xml封装wrapper过程应用事件驱动交给ContextConfig(它也是一个事件监听器)

9. MapperListener.startInternal()

public void startInternal() throws LifecycleException {        setState(LifecycleState.STARTING);        // 失去 engine 容器        Engine engine = service.getContainer();        if (engine == null) {            return;        }        // 找到默认主机        findDefaultHost();        // 为以后容器以及子容器增加监听器        addListeners(engine);        // 注册engine下所有的host        Container[] conHosts = engine.findChildren();        for (Container conHost : conHosts) {            Host host = (Host) conHost;            if (!LifecycleState.NEW.equals(host.getState())) {                // 注册上下文和包装器                registerHost(host);            }        }    }

10. Connector.startInternal()

截至到这里,容器的注册与启动曾经实现了,接下来到连接器的启动了

protected void startInternal() throws LifecycleException {    // Validate settings before starting    if (getPort() < 0) {        throw new LifecycleException(sm.getString(            "coyoteConnector.invalidPort", Integer.valueOf(getPort())));    }    setState(LifecycleState.STARTING);    try {        protocolHandler.start();    } catch (Exception e) {        throw new LifecycleException(            sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);    }}

11. AbstractProtocol.start()

这里对 EndPoint进行初始化

public void start() throws Exception {    if (getLog().isInfoEnabled()) {        getLog().info(sm.getString("abstractProtocolHandler.start", getName()));    }    endpoint.start();    // Start timeout thread    asyncTimeout = new AsyncTimeout();    Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");    int priority = endpoint.getThreadPriority();    if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {        priority = Thread.NORM_PRIORITY;    }    timeoutThread.setPriority(priority);    timeoutThread.setDaemon(true);    timeoutThread.start();}

12. AbstractEndpoint.start()

public final void start() throws Exception {    if (bindState == BindState.UNBOUND) {        bind();        bindState = BindState.BOUND_ON_START;    }    startInternal();}

13. NioEndpoint.bind()

public void bind() throws Exception {    if (!getUseInheritedChannel()) {        // 获取 nio 通道 channel        serverSock = ServerSocketChannel.open();        socketProperties.setProperties(serverSock.socket());        InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));        // 绑定端口,但尚未应用 accept 获取客户端连贯        serverSock.socket().bind(addr,getAcceptCount());    } else {        // Retrieve the channel provided by the OS        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    // Initialize thread count defaults for acceptor, poller    if (acceptorThreadCount == 0) {        // FIXME: Doesn't seem to work that well with multiple accept threads        acceptorThreadCount = 1;    }    if (pollerThreadCount <= 0) {        //minimum one poller thread        pollerThreadCount = 1;    }    setStopLatch(new CountDownLatch(pollerThreadCount));    // Initialize SSL if needed    initialiseSsl();    selectorPool.open();}

14. NioEndpoint.startInternal()

这里通过startAcceptorThreads启动Accepter线程,该线程用于接管新的Socket连贯

总结