Tomcat04-- source tracking tomcat initialization and startup process

1. Source inlet

In catalina.bat bin directory, the following code is set MAINCLASS = org.apache.catalina.startup.Bootstrap, indicates the location of the main class tomcat class is started.

Start of Location: org / apache / catalina / startup / Bootstrap.java

2. initialization process

2.1 The main class initialization

2.1.1 calls the init () method to initialize

if (daemon == null) {
    // Don't set daemon until init() has completed
    Bootstrap bootstrap = new Bootstrap();
    try {
          bootstrap.init();
    } catch (Throwable t) {
           handleThrowable(t);
           t.printStackTrace();
           return;
     }
     daemon = bootstrap;
} 

2.1.2 group class init () method

The main role is to create an init target Catalina

Look at the comments section of the main code Chinese

 public void init() throws Exception {
        // 初始化类加载器
        initClassLoaders();

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");

        // 通过反射创建Catalina对象
        Object startupInstance = startupClass.getConstructor().newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        // 将Catalina对象startupInstance赋值给catalinaDaemon
        catalinaDaemon = startupInstance;
    }

2.1.3 main class load is executed after the initialization method

After the master class initialization, we begin to execute some command parameters statement

try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            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);
            } else {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } 

Command parameters, find the corresponding load method, where to start, for example:

 private void load(String[] arguments) throws Exception {

        // Call the load() method
        String methodName = "load";
        Object param[];
        Class<?> paramTypes[];
        if (arguments==null || arguments.length==0) {
            paramTypes = null;
            param = null;
        } else {
            paramTypes = new Class[1];
            paramTypes[0] = arguments.getClass();
            param = new Object[1];
            param[0] = arguments;
        }
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {
            log.debug("Calling startup class " + method);
        }
        // 调用catalina的load方法
        method.invoke(catalinaDaemon, param);
    }

2.2 Catalina

Then performs load method catalina

public void load(String args[]) {

        try {
            if (arguments(args)) {
                // 调用load的重载方法,执行逻辑
                load();
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }

Then there is the Senate load no-argument method call to the load

getServer().init();

2.2.1 Creating xml parsing tool of tomcat

// Digester是tomcat的xml文件解析根据,解析server.xml
Digester digester = createStartDigester();

2.2.2 Server Object get

After a series of treatments, in execution

getServer().init();

Get Server object, and then call the Server object's init () method

2.3 Server

In the component tomcat, there LifeCycle interface to a life cycle, it has achieved a class LifeCycleBase, getServer () init ();. Init is actually called in the init method LifeCycleBase.

 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());
        }
    }

Found in init in turn calls the initInternal method. initInternal is LifeCycleBase abstract methods, so the final call of this method is to initInternal class implementation, that is, the implementation class called Server StandardServer of initInternal.

Enter initInternal method, where they call the service's init method

// 一个Server下可以有多个service
for (int i = 0; i < services.length; i++) {
   services[i].init();
}

2.4 Service

Like the previous procedure, find StandardService of initInternal, respectively initialization engine (engine), actuators (Executor), connectors (Connector)

protected void initInternal() throws LifecycleException {

        super.initInternal();

        if (engine != null) {
            // 初始化引擎
            engine.init();
        }

        // Initialize any Executors
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            // 初始化执行器
            executor.init();
        }

        // Initialize mapper listener
        mapperListener.init();

        // Initialize our defined Connectors
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
                try {
                    // 初始化连接器
                    connector.init();
                } catch (Exception e) {
                    String message = sm.getString(
                            "standardService.connector.initFailed", connector);
                    log.error(message, e);

                    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
                        throw new LifecycleException(message);
                }
            }
        }
    }

2.5 Connector

Initializing a lot of components in the Service, these component initialization are similar, here we focus on what Connector.

Connector is not an interface, so a direct call its methods initInternal.

2.5.1 Creating Adapter

adapter = new CoyoteAdapter(this);

2.5.2 initialization protocolHandler

try {
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }

3. Start Process

In BootStrap main function, load methods below, followed by the start method, then we look at the code along tomcat startup process.

daemon.start();

First of all, it calls itself the start method, and then call the start method Catalina

public void start() throws Exception {
        if (catalinaDaemon == null) {
            init();
        }

        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 调用catalina的start方法
        method.invoke(catalinaDaemon, (Object [])null);
    }

Then, Catalina's start method, to call the start method of Server

try {
   getServer().start();
}

And it uses a template design patterns, come LifeCycleBase, perform business logic implementation classes start of each interface in the start method by startInternal method.

Here referring to the next start Connector connector object in focus, call startInternal method Connector, and then call the start method of protocolHandler

try {
  protocolHandler.start();
} 

Finally, the program will go to the start method AbsTractEndpoint

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

Execution startInternal () method, because it is Http / 1.1, it will execute startInternal method NioEndpoint in the final surface of this method, the calling thread has an open

// 开启线程
startAcceptorThreads();
protected final void startAcceptorThreads() {
        int count = getAcceptorThreadCount();
        // 接受客户端的请求对象
        acceptors = new Acceptor[count];

        // 开启线程
        for (int i = 0; i < count; i++) {
            // 创建线程对象
            acceptors[i] = createAcceptor();
            String threadName = getName() + "-Acceptor-" + i;
            acceptors[i].setThreadName(threadName);
            Thread t = new Thread(acceptors[i], threadName);
            t.setPriority(getAcceptorThreadPriority());
            t.setDaemon(getDaemon());
            t.start();
        }
    }

 createAcceptor():

protected AbstractEndpoint.Acceptor createAcceptor() {
        return new Acceptor();
    }

Acceptor():

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();

                    SocketChannel socket = null;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        socket = serverSock.accept();
                    } catch (IOException ioe) {
                        // We didn't get a socket
                        countDownConnection();
                        if (running) {
                            // Introduce delay if necessary
                            errorDelay = handleExceptionWithDelay(errorDelay);
                            // re-throw
                            throw ioe;
                        } 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;
        }

Acceptor run method, there is for receiving the code word a client's request, as follows:

socket = serverSock.accept();

And waits for receiving a request from the client.

So far, start the process ends!

to sum up:

        And tracking the source from the start flowchart, it can be seen tomcat startup process is standardized, unified start of the life cycle management interface definition LifeCycle, first calls init () method for the stepwise assembly initialization operation, and then call start ( ) method to start.

        Lifecycle management components in addition to the completion of each stage of the process itself, but also responsible for calling in response to the sub-assemblies, components and between the components are loosely coupled, because we can easily be modified and replaced by a configuration file.

Published 128 original articles · won praise 6 · views 3220

Guess you like

Origin blog.csdn.net/weixin_43318134/article/details/103941160