tomcat

作者: 7d972d5e05e8 | 来源:发表于2020-06-24 16:50 被阅读0次

一、tomcat8之后,默认nio模式

相对8以前默认BIO模式,一个请求创建一个线程处理。现在nio后,是不是还是一个请求创建一个线程呢?我们直接上tomcat的
org.apache.tomcat.util.net.AbstractEndpoint#processSocket源码:

 /**
     * Process the given SocketWrapper with the given status. Used to trigger
     * processing as if the Poller (for those endpoints that have one)
     * selected the socket.
     *
     * @param socketWrapper The socket wrapper to process
     * @param event         The socket event to be processed
     * @param dispatch      Should the processing be performed on a new
     *                          container thread
     *
     * @return if processing was triggered successfully
     */
    public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        try {
            if (socketWrapper == null) {
                return false;
            }
            SocketProcessorBase<S> sc = processorCache.pop();
            if (sc == null) {
                sc = createSocketProcessor(socketWrapper, event);
            } else {
                sc.reset(socketWrapper, event);
            }
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
          //通过线程池去执行请求
                executor.execute(sc);
            } else {
                sc.run();
            }
        } catch (RejectedExecutionException ree) {
            getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            getLog().error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    }

总结:NIO模式下,是通过线程池去执行请求处理的。这个线程池不是NIO事件驱动线程模型里面的,NIO包含自己的主线程和worker线程。这个线程池,应该是纯粹的process request用的线程。

我们看下这个executor是怎么被初始化的?源码位置:org.apache.tomcat.util.net.AbstractEndpoint#createExecutor

public void createExecutor() {
        internalExecutor = true;
        TaskQueue taskqueue = new TaskQueue();
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }

线程池大小:核心线程数取决于getMinSpareThreads(),默认是10,最大线程数getMaxThreads()默认200。如下AbstractEndpoint类的配置:

private int minSpareThreads = 10;
private int maxThreads = 200;

拒绝策略直接就是new RejectHandler()类,简单粗暴的抛出异常出去。

下面看下Spring是怎么触发tomcat的调用堆栈:


image.png

Spring在容器初始化完成后,调用org.springframework.context.support.AbstractApplicationContext#finishRefresh:

// Last step: publish corresponding event.
finishRefresh();

这里面会执行startEmbeddedServletContainer方法,用来初始化Servlet相关的东西,进一步触发tomcat相关对象的初始化。都在上面的调用链路里面,有兴趣可以自己断点debug看下。

相关文章

网友评论

      本文标题:tomcat

      本文链接:https://www.haomeiwen.com/subject/sjorfktx.html