tomcat 如何优雅关闭?

在Bootstrap类中
public final class Bootstrap {
  public static void main(String[] args) {

    System.setProperty("catalina.base", System.getProperty("user.dir"));
    Connector connector = new HttpConnector();

    Wrapper wrapper1 = new StandardWrapper();//表示一个servlet容器
    wrapper1.setName("Primitive");
    wrapper1.setServletClass("PrimitiveServlet");
    Wrapper wrapper2 = new StandardWrapper();
    wrapper2.setName("Modern");
    wrapper2.setServletClass("ModernServlet");

    Context context = new StandardContext();
    // StandardContext's start method adds a default mapper
    context.setPath("/app1");
    context.setDocBase("app1");

    context.addChild(wrapper1);
    context.addChild(wrapper2);

    LifecycleListener listener = new SimpleContextConfig();
    ((Lifecycle) context).addLifecycleListener(listener);

    Host host = new StandardHost();
    host.addChild(context);
    host.setName("localhost");
    host.setAppBase("webapps");

    Loader loader = new WebappLoader();
    context.setLoader(loader);
    // context.addServletMapping(pattern, name);
    context.addServletMapping("/Primitive", "Primitive");
    context.addServletMapping("/Modern", "Modern");

    Engine engine = new StandardEngine();
    engine.addChild(host);
    engine.setDefaultHost("localhost");

    Service service = new StandardService();
    service.setName("Stand-alone Service");

    Server server = new StandardServer();
    server.addService(service);

    service.addConnector(connector);
    //StandardService class's setContainer will call all its connector's setContainer method
    service.setContainer(engine);

    // Start the new server
    if (server instanceof Lifecycle) {
      try {
        //最终调用services[i].initialize(); 该方法用于初始化添加到其中的所有连接器.
        //那么连接器要初始化什么东西呢?-->打开socket开始监听
        server.initialize();


        //该方法最后会启动container,connectors。利用for启动多个。
        //那么启动什么东西呢?-->每一个组件启动都会发送相关事件,
        ((Lifecycle) server).start();
        server.await();//等待关闭命令--这里关闭
        // the program waits until the await method returns,
        // i.e. until a shutdown command is received.
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }

    //这里开始关闭啦 !
    if (server instanceof Lifecycle) {
      try {
        ((Lifecycle) server).stop();
      }
      catch (LifecycleException e) {
        e.printStackTrace(System.out);
      }
    }
  }
}

看看StandardServer#await()方法


public void await() {

    // Set up a server socket to wait on
    ServerSocket serverSocket = null;
    try {
        serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
    } catch (IOException e) {
        System.err.println("StandardServer.await: create[" + port + "]: " + e);
        e.printStackTrace();
        System.exit(1);
    }

    // Loop waiting for a connection and a valid command
    while (true) {

        // Wait for the next connection
        Socket socket = null;
        InputStream stream = null;
        try {
            socket = serverSocket.accept();
            socket.setSoTimeout(10 * 1000);  // Ten seconds
            stream = socket.getInputStream();
        } catch (AccessControlException ace) {
            System.err.println("StandardServer.accept security exception: " + ace.getMessage());
            continue;
        } catch (IOException e) {
            System.err.println("StandardServer.await: accept: " + e);
            e.printStackTrace();
            System.exit(1);
        }

        // Read a set of characters from the socket
        StringBuffer command = new StringBuffer();
        int expected = 1024; // Cut off to avoid DoS attack
        while (expected < shutdown.length()) {
            if (random == null)
                random = new Random(System.currentTimeMillis());
            expected += (random.nextInt() % 1024);
        }
        while (expected > 0) {
            int ch = -1;
            try {
                ch = stream.read();
            } catch (IOException e) {
                System.err.println("StandardServer.await: read: " + e);
                e.printStackTrace();
                ch = -1;
            }
            if (ch < 32)  // Control character or EOF terminates loop
                break;
            command.append((char) ch);
            expected--;
        }

        // Close the socket now that we are done with it
        try {
            socket.close();
        } catch (IOException e) {
            ;
        }

        // Match against our command string
        boolean match = command.toString().equals(shutdown);
        if (match) {
            break;
        } else
            System.err.println("StandardServer.await: Invalid command '" +
                               command.toString() + "' received");

    }

    // Close the server socket and return
    try {
        serverSocket.close();
    } catch (IOException e) {
        ;
    }

}










先调用StandardServer的stop()方法 关闭与它关联的组件

StandardServer
public void stop() throws LifecycleException {

    // Validate and update our current component state
    if (!started)
        throw new LifecycleException(sm.getString("standardServer.stop.notStarted"));

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;

    // Stop our defined Services
    for (int i = 0; i < services.length; i++) {
        if (services[i] instanceof Lifecycle)
            ((Lifecycle) services[i]).stop();//关闭所有service,即调用StandardService的stop()
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

}


复制代码

StandardService
public void stop() throws LifecycleException {

    // Validate and update our current component state
    if (!started) {
        throw new LifecycleException
            (sm.getString("standardService.stop.notStarted"));
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

    lifecycle.fireLifecycleEvent(STOP_EVENT, null);

    System.out.println
        (sm.getString("standardService.stop.name", this.name));
    started = false;

    // Stop our defined Connectors first
    synchronized (connectors) {
        for (int i = 0; i < connectors.length; i++) {
            if (connectors[i] instanceof Lifecycle)
                ((Lifecycle) connectors[i]).stop();//1关闭连接器
        }
    }

    // Stop our defined Container second
    if (container != null) {
        synchronized (container) {
            if (container instanceof Lifecycle) {
                ((Lifecycle) container).stop();//2关闭容器
            }
        }
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

}复制代码

#1:for循环关闭所有连接器。(即调用connector的stop方法)如下

HttpConnector
public void stop() throws LifecycleException {

    // Validate and update our current state
    if (!started)
        throw new LifecycleException(sm.getString("httpConnector.notStarted"));
    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;

    // Gracefully shut down all processors we have created
    for (int i = created.size() - 1; i >= 0; i--) {
        HttpProcessor processor = (HttpProcessor) created.elementAt(i);
        if (processor instanceof Lifecycle) {
            try {
                ((Lifecycle) processor).stop();//1)
            } catch (LifecycleException e) {
                log("HttpConnector.stop", e);
            }
        }
    }

    synchronized (threadSync) {
        // Close the server socket we were using
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {

            }
        }
        // Stop our background thread
        threadStop();
    }
    serverSocket = null;

}

1)关闭所有processor。代码如下
public void stop() throws LifecycleException {

    if (!started)
        throw new LifecycleException(sm.getString("httpProcessor.notStarted"));
    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;

    threadStop();

}
private void threadStop() {

    log(sm.getString("httpProcessor.stopping"));

    stopped = true;
    assign(null);

    if (status != Constants.PROCESSOR_IDLE) {
        // Only wait if the processor is actually processing a command
        synchronized (threadSync) {
            try {
                threadSync.wait(5000);
            } catch (InterruptedException e) {
                ;
            }
        }
    }
    thread = null;

}

复制代码


#2:关闭container组件。调用其stop方法。

StandardContext复制代码

public synchronized void stop() throws LifecycleException {

    // Validate and update our current component state
    if (!started)
        throw new LifecycleException(sm.getString("containerBase.notStarted", logName()));
    if (debug >= 1)
        log("Stopping");
    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
    // Mark this application as unavailable while we shut down
    setAvailable(false);//服务设为不可用
    // Binding thread
    ClassLoader oldCCL = bindThread();
    // Stop our filters
    filterStop();//关闭过滤器

    // Finalize our character set mapper
    setCharsetMapper(null);

    if ((manager != null) && (manager instanceof Lifecycle)) {
        ((Lifecycle) manager).stop();//关闭管理器
    }

    // Normal container shutdown processing
    if (debug >= 1)
        log("Processing standard container shutdown");
    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;

    try {
        // Stop the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).stop();//关闭管道
        }
        // Stop our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Lifecycle)
                ((Lifecycle) children[i]).stop();//关闭所有子容器
        }
        // Stop our Mappers, if any
        Mapper mappers[] = findMappers();
        for (int i = 0; i < mappers.length; i++) {
            if (mappers[(mappers.length-1)-i] instanceof Lifecycle)
                ((Lifecycle) mappers[(mappers.length-1)-i]).stop();//关闭映射器
        }
        // Stop our application listeners
        listenerStop();//关闭监听器
        // Stop our subordinate components, if any
        if (resources != null) {
            if (resources instanceof Lifecycle) {
                ((Lifecycle) resources).stop();
            } else if (resources instanceof ProxyDirContext) {
                DirContext dirContext =
                    ((ProxyDirContext) resources).getDirContext();
                if (dirContext != null) {
                    if (debug >= 1) {
                        log("Releasing document base " + docBase);
                    }
                    if (dirContext instanceof BaseDirContext) {
                        ((BaseDirContext) dirContext).release();
                        if ((dirContext instanceof WARDirContext)
                            || (dirContext instanceof FileDirContext)) {
                            resources = null;
                        }
                    } else {
                        log("Cannot release " + resources);
                    }
                }
            }
        }
        if ((realm != null) && (realm instanceof Lifecycle)) {
            ((Lifecycle) realm).stop();
        }
        if ((cluster != null) && (cluster instanceof Lifecycle)) {
            ((Lifecycle) cluster).stop();
        }
        if ((logger != null) && (logger instanceof Lifecycle)) {
            ((Lifecycle) logger).stop();
        }
        if ((loader != null) && (loader instanceof Lifecycle)) {
            ((Lifecycle) loader).stop();
        }

    } finally {

        // Unbinding thread
        unbindThread(oldCCL);

    }

    // Reset application context
    context = null;

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

    if (debug >= 1)
        log("Stopping complete");

}复制代码



转载于:https://juejin.im/post/5b1602846fb9a01e345b966f

你可能感兴趣的:(tomcat 如何优雅关闭?)