一、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看下。











网友评论