tomcat多线程处理请求,tomcat中的nio线程模型
目录
一、前言二、tomcat结构三、探讨雄猫是如何处理请求1、初始化2、如何处理客户端请求总结
一、前言
JAVA后端项目,运行在容器雄猫中,由于现在跳羚的内置雄猫容器,其默认配置屏蔽了很多对雄猫的认知,但是对雄猫的学习和认识是比较重要的,所以专门查资料加深了理解,本文主要讨论在跳羚集成下的tomcat9的请求过程,线程模型为NIO。
二、tomcat结构
找了张结构图,每个模块的意思和作用就不详解了,可以搜其他文章
三、探讨tomcat是如何处理请求
自己画了一个连接器的结构
1、初始化
在跳羚启动后,组织。spring框架。语境。支持。abstractapplicationcontext #完成刷新,这里进去调用org。spring框架。靴子。网络。servlet。语境。web服务器startstoplifecycle。开始()方法启动TomcatWebServer,初始化雄猫.
通过这样的调用链到达org。阿帕奇。雄猫。util。网。nio端点# start internal(),进行初始化端点中的接受者和民意测验者,这两者都实现了可追捕的接口,初始化后就通过线程开始启动了。
2、如何处理客户端请求
接受者:接收器,作用是接受套接字网络请求,并调用setSocketOptions()封装成为NioSocketWrapper,并注册到轮询器的事件中。注意查看奔跑方法org。阿帕奇。雄猫。util。网。接受者#运行
@ Override public void run(){ int error delay=0;尝试{ //循环,直到我们在(!(!idspnonenote)中收到关闭命令. stopCalled) { //如果在(endpoint.isPaused()!停止调用){ state=接受者状态.暂停;试试{线程。睡眠(50);} catch(中断的异常e){//Ignore } } if(停止调用){ break}状态=AcceptorState .跑步;尝试{//如果我们已经达到最大连接数,请等待端点。countuporawaitconnection();//端点在等待闩锁时可能已暂停//如果是这种情况,则不接受新连接,如果(恩德波伊
nt.isPaused()) { continue; } U socket = null; try { // 等待下一个请求进来 socket = endpoint.serverSocketAccept(); } catch (Exception ioe) { // We didnt get a socket endpoint.countDownConnection(); if (endpoint.isRunning()) { // 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 (!stopCalled && !endpoint.isPaused()) { // 注册socket到Poller,生成PollerEvent事件 if (!endpoint.setSocketOptions(socket)) { endpoint.closeSocket(socket); } } else { endpoint.destroySocket(socket); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); String msg = sm.getString("endpoint.accept.fail"); // APR specific. // Could push this down but not sure it is worth the trouble. if (t instanceof Error) { Error e = (Error) t; if (e.getError() == 233) { // Not an error on HP-UX so log as a warning // so it can be filtered out on that platform // See bug 50273 log.warn(msg, t); } else { log.error(msg, t); } } else { log.error(msg, t); } } } } finally { stopLatch.countDown(); } state = AcceptorState.ENDED; }Poller
:轮询器,轮询是否有事件达到,有请求事件到达后,以NIO的处理方式,查询Selector取出所有请求,遍历每个请求的需求,分配给Executor线程池执行。查看org.apache.tomcat.util.net.NioEndpoint.Poller#run()
public void run() { // Loop until destroy() is called while (true) { boolean hasEvents = false; try { if (!close) { hasEvents = events(); if (wakeupCounter.getAndSet(-1) > 0) { // If we are here, means we have other stuff to do // Do a non blocking select keyCount = selector.selectNow(); } else { keyCount = selector.select(selectorTimeout); } wakeupCounter.set(0); } if (close) { events(); timeout(0, false); try { selector.close(); } catch (IOException ioe) { log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe); } break; } // Either we timed out or we woke up, process events first if (keyCount == 0) { hasEvents = (hasEvents events()); } } catch (Throwable x) { ExceptionUtils.handleThrowable(x); log.error(sm.getString("endpoint.nio.selectorLoopError"), x); continue; }//查询selector取出所有请求 Iterator<SelectionKey> iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null; // Walk through the collection of ready keys and dispatch // any active event. while (iterator != null && iterator.hasNext()) { SelectionKey sk = iterator.next(); iterator.remove(); NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment(); //处理请求key if (socketWrapper != null) { processKey(sk, socketWrapper); } } // Process timeouts timeout(keyCount,hasEvents); } getStopLatch().countDown(); }
请求过程大致如下图:
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注盛行IT的更多内容!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。