- 浏览: 6908 次
- 性别:
- 来自: 北京
文章分类
最新评论
费了九牛二虎之力,tomcat终于启动起来了,接下来我们要看看tomcat是如何处理一个请求的。上回 说到JIoEndpoint是负责处理请求的,这个类里面有几个内部接口和内部类,其中有一个就是我们要关注的Acceptor
// --------------------------------------------------- Acceptor Inner Class /** * Server socket acceptor thread. */ protected class Acceptor implements Runnable { /** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. */ @Override public void run() { int errorDelay = 0; // Loop until we receive a shutdown command while (running) { // Loop if endpoint is paused while (paused && running) { try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } } if (!running) { break; } try { //超过最大连接数,就等待 //if we have reached max connections, wait countUpOrAwaitConnection(); Socket socket = null; try { // Accept the next incoming connection from the server // socket socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { /** * 触发一种延迟处理,如果errorDelay>0,线程会sleep相应的毫秒,主要是为后面的程序处理异常 * 争取时间,从而避免在短时间大量占用CPU * 每多一个异常,会延迟50ms,直到达到最大阀值1.6s **/ // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw throw ioe; } // Successful accept, reset the error delay errorDelay = 0; // Configure the socket if (setSocketOptions(socket)) { // Hand this socket off to an appropriate processor if (!processSocket(socket)) { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } } else { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } } catch (IOException x) { if (running) { log.error(sm.getString("endpoint.accept.fail"), x); } } catch (NullPointerException npe) { if (running) { log.error(sm.getString("endpoint.accept.fail"), npe); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("endpoint.accept.fail"), t); } // The processor will recycle itself when it finishes } } }
前面说过,JIoEndpoint启动了多个Acceptor来处理请求,每个Acceptor都是一个线程,Acceptor的run方法里主要就是调用processSocket(socket),这是JIoEndpoint里的方法,进入这个方法看一下
/** * Process a new connection from a new client. Wraps the socket so * keep-alive and other attributes can be tracked and then passes the socket * to the executor for processing. * * @param socket The socket associated with the client. * * @return <code>true</code> if the socket is passed to the * executor, <code>false</code> if something went wrong or * if the endpoint is shutting down. Returning * <code>false</code> is an indication to close the socket * immediately. */ protected boolean processSocket(Socket socket) { // Process the request from this socket try { SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket); wrapper.setKeepAliveLeft(getMaxKeepAliveRequests()); // During shutdown, executor may be null - avoid NPE if (!running) { return false; } getExecutor().execute(new SocketProcessor(wrapper)); } catch (RejectedExecutionException x) { log.warn("Socket processing request was rejected for:"+socket,x); 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 log.error(sm.getString("endpoint.process.fail"), t); return false; } return true; }
方法的注释已经说的很明白了,它就是将socket包装了一下,以便扩展传递一些扩展属性,接下来调用 getExecutor().execute(new SocketProcessor(wrapper));getExecutor()在前面已经提到过,它是一个线程池对象,里面存放了一个个将要被执行的请求线程。这个SocketProcessor是JIoEndpoint里的另一个内部类,也是一个多线程:
// ------------------------------------------- SocketProcessor Inner Class /** * This class is the equivalent of the Worker, but will simply use in an * external Executor thread pool. */ protected class SocketProcessor implements Runnable { protected SocketWrapper<Socket> socket = null; protected SocketStatus status = null; public SocketProcessor(SocketWrapper<Socket> socket) { if (socket==null) throw new NullPointerException(); this.socket = socket; } public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) { this(socket); this.status = status; } @Override public void run() { boolean launch = false; synchronized (socket) { try { SocketState state = SocketState.OPEN; try { //首先对ssl请求做特殊处理,如果不是ssl请求,这个方法什么也不做 // SSL handshake serverSocketFactory.handshake(socket.getSocket()); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); if (log.isDebugEnabled()) { log.debug(sm.getString("endpoint.err.handshake"), t); } // Tell to close the socket state = SocketState.CLOSED; } //如果不是ssl请求 if ((state != SocketState.CLOSED)) { //处理请求 if (status == null) { state = handler.process(socket, SocketStatus.OPEN); } else { state = handler.process(socket,status); } } if (state == SocketState.CLOSED) { // Close socket if (log.isTraceEnabled()) { log.trace("Closing socket:"+socket); } countDownConnection();//处理连接数 try { socket.getSocket().close();//关闭socket连接 } catch (IOException e) { // Ignore } } else if (state == SocketState.OPEN){ socket.setKeptAlive(true); socket.access(); launch = true; } else if (state == SocketState.LONG) { socket.access(); waitingRequests.add(socket); } } finally { if (launch) { try { getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN)); } catch (NullPointerException npe) { if (running) { log.error(sm.getString("endpoint.launch.fail"), npe); } } } } } socket = null; // Finish up this request } }
我们看一下实际请求的处理state = handler.process(socket, SocketStatus.OPEN);这个handler是什么东西?具体的协议对象,在这里是Http11Protocol对象实例。我们先看一下Http11Protocol的类关系图:
process方法在AbstractProtocol类的静态内部类AbstractConnectionHandler里:
public SocketState process(SocketWrapper<S> socket, SocketStatus status) { /**将socket从connections Map里移除,这只针对SocketState.LONG的情况有效**/ P processor = connections.remove(socket.getSocket()); socket.setAsync(false); try { if (processor == null) { processor = recycledProcessors.poll();//从池里取得一个processor } if (processor == null) { processor = createProcessor();//没有就新建一个processor } initSsl(socket, processor); SocketState state = SocketState.CLOSED; do { if (processor.isAsync() || state == SocketState.ASYNC_END) { state = processor.asyncDispatch(status); } else if (processor.isComet()) {//如果是comet state = processor.event(status);//tomcat不支持comet,所以此方法只是简单的抛出异常 } else {//普通的处理 state = processor.process(socket); } if (state != SocketState.CLOSED && processor.isAsync()) { state = processor.asyncPostProcess(); } } while (state == SocketState.ASYNC_END); if (state == SocketState.LONG) { // In the middle of processing a request/response. Keep the // socket associated with the processor. Exact requirements // depend on type of long poll longPoll(socket, processor); } else if (state == SocketState.OPEN){ // In keep-alive but between requests. OK to recycle // processor. Continue to poll for the next request. release(socket, processor, false, true);//释放processor } else { // Connection closed. OK to recycle the processor. release(socket, processor, true, false);//释放processor } return state; } catch(java.net.SocketException e) { // SocketExceptions are normal getLog().debug(sm.getString( "ajpprotocol.proto.socketexception.debug"), e); } catch (java.io.IOException e) { // IOExceptions are normal getLog().debug(sm.getString( "ajpprotocol.proto.ioexception.debug"), e); } // Future developers: if you discover any other // rare-but-nonfatal exceptions, catch them here, and log as // above. catch (Throwable e) { ExceptionUtils.handleThrowable(e); // any other exception or error is odd. Here we log it // with "ERROR" level, so it will show up even on // less-than-verbose logs. getLog().error(sm.getString("ajpprotocol.proto.error"), e); } release(socket, processor, true, false); return SocketState.CLOSED; }
先说下relese(socket,processor,true,false)方法,这个方法虽然带了4个参数,但目前实际使用的只有前2个参数,后2个直接没管了,不知道是留着后续扩展的目的?此方法在Http11Protocol类的内部类Http11ConnectionHandler
/** * Expected to be used by the handler once the processor is no longer * required. * * @param socket Not used in BIO * @param processor * @param isSocketClosing Not used in HTTP * @param addToPoller Not used in BIO */ @Override public void release(SocketWrapper<Socket> socket, Http11Processor processor, boolean isSocketClosing, boolean addToPoller) { processor.recycle(); recycledProcessors.offer(processor); }
回去看processor吧,首先我们要知道我们的processor是哪个对象:
@Override protected Http11Processor createProcessor() { Http11Processor processor = new Http11Processor( proto.getMaxHttpHeaderSize(), (JIoEndpoint)proto.endpoint, proto.getMaxTrailerSize()); processor.setAdapter(proto.adapter); processor.setMaxKeepAliveRequests(proto.getMaxKeepAliveRequests()); processor.setKeepAliveTimeout(proto.getKeepAliveTimeout()); processor.setConnectionUploadTimeout( proto.getConnectionUploadTimeout()); processor.setDisableUploadTimeout(proto.getDisableUploadTimeout()); processor.setCompressionMinSize(proto.getCompressionMinSize()); processor.setCompression(proto.getCompression()); processor.setNoCompressionUserAgents(proto.getNoCompressionUserAgents()); processor.setCompressableMimeTypes(proto.getCompressableMimeTypes()); processor.setRestrictedUserAgents(proto.getRestrictedUserAgents()); processor.setSocketBuffer(proto.getSocketBuffer()); processor.setMaxSavePostSize(proto.getMaxSavePostSize()); processor.setServer(proto.getServer()); processor.setDisableKeepAlivePercentage( proto.getDisableKeepAlivePercentage()); register(processor); return processor; }
Http11Processor与Http11Protocol有类似类关系图的Http11Processor--->AbstractHttp11Processor-->AbstractProcessor-->Processor
AbstractProcessor虽然是个抽象类,但它有自己的构造函数
public AbstractProcessor(AbstractEndpoint endpoint) { this.endpoint = endpoint; asyncStateMachine = new AsyncStateMachine(this); request = new Request(); response = new Response(); response.setHook(this); request.setResponse(response); }
之所以提到这个构造函数,因为它生成了request和response对象,后面我们需要围绕这两个对象团团转,还是在此先供奉一下吧,把它老人家的底细弄清楚了,后面才不至于被这两活宝糊弄。
我们回到processor.process(socket);的处理,这个方法所作的事情就是解析http请求数据,组装request和response对象,最后将response输出,详细的细节,我们下节讨论。到目前为止我们已经把请求请到家里来了,并且我们知道后面谁会去处理这些东西,后面接下来要解决的就是,如何去解析、处理这个请求了,欲知后事如何,且听下回分解。
发表评论
-
tomcat源码分析系列之请求处理---大厨颠勺
2011-08-13 22:04 0上一回,我们已经吃上了香喷喷的狗肉,味道好是好,但作为 ... -
tomcat源码分析系列之请求处理---关门打狗
2011-08-13 17:06 1484上回我们把请求放进来了,这回我们关上门,好好修理修理它 ... -
tomcat源码分析系列之启动---庐山真面目
2011-08-11 23:28 1460上回我们说到Http11Protocol,它的ini ... -
tomcat源码分析系列之启动
2011-07-31 16:36 1466对于tomcat这么一个庞大的东西,要去分析 ... -
tomcat源码分析系列之启动---暗度陈仓
2011-08-10 22:27 1171前面我们分析了tomcat是如何启动的,但我们好像 ... -
tomcat源码分析系列之HTTP
2011-07-25 23:33 0tomcat是一个web容器,对于互联网来说,H ... -
tomcat源码分析系列之前言
2011-07-24 11:40 30我这人很懒,工作中经常使用tomcat,一直以来就 ...
相关推荐
初中语文文摘社会请君入瓮除迷信
(备战中考)中考语文课外文言文专练请君入瓮.docx
Scapy(Ether、ARP、srp1模块介绍)、Scanner脚本编写[ARP数据包的构造]
智能制造的数字化工厂规划qytp.pptx
罗兰贝格:德隆人力资源管理体系gltp.pptx
JAVA3D的网络三维技术的设计与实现
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
基于J2EE的B2C电子商务系统开发
麦肯锡_xx保险员工培训咨询报告gltp.pptx
JAVA社区网络服务系统
备自投tp.pptx
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
JSP高校教务排课管理系统,管理员角色包含以下功能:课程申请管理,课程设置管理,课程情况查看,专业设置查看,排课管理,系办人员管理,教师管理,学生管理,教室管理,班级管理,管理员登录等功能。教师角色包含以下功能:教师角色登录,申请增加课程,学生管理,成绩录入管理,课程安排管理等功能。学生角色包含以下功能:学生角色登录,基本信息查看,选课功能安排,课程表查看,成绩查询等功能。 本项目实现的最终作用是基于JSP高校教务排课管理系统 分为3个角色 第1个角色为管理员角色,实现了如下功能: - 专业设置查看 - 学生管理 - 排课管理 - 教室管理 - 教师管理 - 班级管理 - 管理员登录 - 系办人员管理 - 课程情况查看 - 课程申请管理 - 课程设置管理 第2个角色为教师角色,实现了如下功能: - 学生管理 - 成绩录入管理 - 教师角色登录 - 申请增加课程 - 课程安排管理 第3个角色为学生角色,实现了如下功能: - 基本信息查看 - 学生角色登录 - 成绩查询 - 课程表查看 - 选课功能安排
第21章spring-mvc之缓存
华为网盘高级版
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Java聊天室程序(java)
产品线经理转身赋能zzn.pptx
JAVA泡泡堂网络游戏的设计与实现
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。