tomcat原理-3-Spring-boot-web中tomcat启动过程

spring-boot-web中web容器叫WebServer(org.springframework.boot.web.server.WebServer),由WebServerFactory(org.springframework.boot.web.server.WebServerFactory)创建,WebServer支持多种web容器,tomcat是默认使用的容器。

spring-boot-web中tomcat容器叫TomcatWebServer(org.springframework.boot.web.embedded.tomcat.TomcatWebServer),是tomcat(org.apache.catalina.startup.Tomcat)在Spring中的代理,由TomcatReactiveWebServerFactory(org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory)创建。

spring容器在启动的过程中根据ServletWebServerFactoryAutoConfiguration构建相应的BeanDefinition,其中就有TomcatServletWebServerFactory。

Spring容器ServletWebServerApplicationContext中通过onRefresh()方法创建了WebServer,通过finishRefresh()方法启动WebServer,开始对外提供服务。

@Override
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    }
    catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}

@Override
protected void finishRefresh() {
    super.finishRefresh();
    WebServer webServer = startWebServer();
    if (webServer != null) {
        publishEvent(new ServletWebServerInitializedEvent(webServer, this));
    }
}

对createWebServer进行分析

private void createWebServer() {
    WebServer webServer = this.webServer;
    ServletContext servletContext = getServletContext();
    if (webServer == null && servletContext == null) {
        //拿到一个工厂类对象
        ServletWebServerFactory factory = getWebServerFactory();
        //创建相应的webServer
        this.webServer = factory.getWebServer(getSelfInitializer());
    }
    else if (servletContext != null) {
        try {
            getSelfInitializer().onStartup(servletContext);
        }
        catch (ServletException ex) {
            throw new ApplicationContextException("Cannot initialize servlet context",
                    ex);
        }
    }
    initPropertySources();
}

对TomcatServletWebServerFactory中getWebServer进行分析

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
    //创建相关的类对象并配置需要的参数
    Tomcat tomcat = new Tomcat();
    File baseDir = (this.baseDirectory != null ? this.baseDirectory
            : createTempDir("tomcat"));
    tomcat.setBaseDir(baseDir.getAbsolutePath());
    Connector connector = new Connector(this.protocol);
    tomcat.getService().addConnector(connector);
    customizeConnector(connector);
    tomcat.setConnector(connector);
    tomcat.getHost().setAutoDeploy(false);
    configureEngine(tomcat.getEngine());
    for (Connector additionalConnector : this.additionalTomcatConnectors) {
        tomcat.getService().addConnector(additionalConnector);
    }
    prepareContext(tomcat.getHost(), initializers);
    //创建TomcatWebServer对象
    return getTomcatWebServer(tomcat);
}

对startWebServer进行分析

private WebServer startWebServer() {
    WebServer webServer = this.webServer;
    if (webServer != null) {
        webServer.start();
    }
    return webServer;
}

对TomcatWebServer中start()进行分析

@Override
public void start() throws WebServerException {
    synchronized (this.monitor) {//同步锁
        if (this.started) {
            return;
        }
        try {
            //关键代码
            addPreviouslyRemovedConnectors();
            Connector connector = this.tomcat.getConnector();
            if (connector != null && this.autoStart) {
                performDeferredLoadOnStartup();
            }
            checkThatConnectorsHaveStarted();
            this.started = true;
            TomcatWebServer.logger
                    .info("Tomcat started on port(s): " + getPortsDescription(true)
                            + " with context path '" + getContextPath() + "'");
        }
        catch (ConnectorStartFailedException ex) {
            stopSilently();
            throw ex;
        }
        catch (Exception ex) {
            throw new WebServerException("Unable to start embedded Tomcat server",
                    ex);
        }
        finally {
            Context context = findContext();
            ContextBindings.unbindClassLoader(context, context.getNamingToken(),
                    getClass().getClassLoader());
        }
    }
}

private void addPreviouslyRemovedConnectors() {
    Service[] services = this.tomcat.getServer().findServices();
    for (Service service : services) {
        Connector[] connectors = this.serviceConnectors.get(service);
        if (connectors != null) {
            for (Connector connector : connectors) {
                //关键代码
                service.addConnector(connector);
                if (!this.autoStart) {
                    stopProtocolHandler(connector);
                }
            }
            this.serviceConnectors.remove(service);
        }
    }
}

StandardService

@Override
public void addConnector(Connector connector) {

    synchronized (connectorsLock) {
        connector.setService(this);
        Connector results[] = new Connector[connectors.length + 1];
        System.arraycopy(connectors, 0, results, 0, connectors.length);
        results[connectors.length] = connector;
        connectors = results;

        if (getState().isAvailable()) {
            try {
                connector.start();
            } catch (LifecycleException e) {
                log.error(sm.getString(
                        "standardService.connector.startFailed",
                        connector), e);
            }
        }

        // Report this property change to interested listeners
        support.firePropertyChange("connector", null, connector);
    }
}

最终走到了Connector(org.apache.catalina.connector.Connector)中

@Override
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);
    }
}

ProtocolHandler:用来处理Socket相关的东西
最终走到了类org.apache.tomcat.util.net.AbstractEndpoint。
在AbstractEndpoint的一个实现类中有这样一段代码:

protected class Acceptor extends AbstractEndpoint.Acceptor {

    @Override
    public void run() {

        int errorDelay = 0;

        // Loop until we receive a shutdown command
        while (running) {

            // Loop if endpoint is paused
            while (paused && running) {
                state = AcceptorState.PAUSED;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // Ignore
                }
            }

            if (!running) {
                break;
            }
            state = AcceptorState.RUNNING;

            try {
                //if we have reached max connections, wait
                countUpOrAwaitConnection();

                AsynchronousSocketChannel socket = null;
                try {
                    // Accept the next incoming connection from the server
                    // socket
                    //接收网络请求
                    socket = serverSock.accept().get();
                } catch (Exception e) {
                    // We didn't get a socket
                    countDownConnection();
                    if (running) {
                        // Introduce delay if necessary
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        // re-throw
                        throw e;
                    } else {
                        break;
                    }
                }
                // Successful accept, reset the error delay
                errorDelay = 0;

                // Configure the socket
                if (running && !paused) {
                    // setSocketOptions() will hand the socket off to
                    // an appropriate processor if successful
                    //处理网络请求
                    if (!setSocketOptions(socket)) {
                        closeSocket(socket);
                   }
                } else {
                    closeSocket(socket);
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("endpoint.accept.fail"), t);
            }
        }
        state = AcceptorState.ENDED;
    }
上一篇:Spring中自定义事件原理


下一篇:MySQL高性能主从架构的复制原理及配置详解