在默认的配置下Tomcat启动好之后会看到后台上总共有6个线程在运行。其中1个用户线程,剩下5个为守护线程(如下图所示)。
如果你对用户线程、守护线程等概念不熟悉,请参看前一篇文章——Tomcat7服务器关闭原理。
这里重点关注以http-bio-8080开头的两个守护线程(即http-bio-8080-Acceptor-0和http-bio-8080-AsyncTimeout),因为这是我们在Tomcat的默认配置下发布web应用时实际处理请求的线程。先看下这两个线程在容器启动时是如何产生和启动的。
在前面将Tomcat启动的系列文章中看到Tomcat容器启动时会用Digester读取server.xml文件产生相应的组件对象并采取链式调用的方式调用它们的init和start方法,在Digester读取到server.xml中的connector节点时是这么处理的:
digester.addRule("Server/Service/Connector", new ConnectorCreateRule()); digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[]{"executor"})); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector");
以上代码见org.apache.catalina.startup.Catalina类的366到372行。所以在碰到server.xml文件中的Server/Service/Connector节点时将会触发ConnectorCreateRule类的begin方法的调用:
public void begin(String namespace, String name, Attributes attributes) throws Exception { Service svc = (Service)digester.peek(); Executor ex = null; if ( attributes.getValue("executor")!=null ) { ex = svc.getExecutor(attributes.getValue("executor")); } Connector con = new Connector(attributes.getValue("protocol")); if ( ex != null ) _setExecutor(con,ex); digester.push(con); }
在第8行,会根据配置文件中Server/Service/Connector节点的protocol属性调用org.apache.catalina.connector.Connector类的构造方法,而默认情况下server.xml文件中Server/Service/Connector节点共有两处配置:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
先看第一个Connector节点,调用Connector的构造方法时会传入字符串HTTP/1.1
public Connector(String protocol) { setProtocol(protocol); // Instantiate protocol handler try { Class<?> clazz = Class.forName(protocolHandlerClassName); this.protocolHandler = (ProtocolHandler) clazz.newInstance(); } catch (Exception e) { log.error(sm.getString( "coyoteConnector.protocolHandlerInstantiationFailed"), e); } }
这里先会执行org.apache.catalina.connector.Connector类的setProtocol方法:
public void setProtocol(String protocol) { if (AprLifecycleListener.isAprAvailable()) { if ("HTTP/1.1".equals(protocol)) { setProtocolHandlerClassName ("org.apache.coyote.http11.Http11AprProtocol"); } else if ("AJP/1.3".equals(protocol)) { setProtocolHandlerClassName ("org.apache.coyote.ajp.AjpAprProtocol"); } else if (protocol != null) { setProtocolHandlerClassName(protocol); } else { setProtocolHandlerClassName ("org.apache.coyote.http11.Http11AprProtocol"); } } else { if ("HTTP/1.1".equals(protocol)) { setProtocolHandlerClassName ("org.apache.coyote.http11.Http11Protocol"); } else if ("AJP/1.3".equals(protocol)) { setProtocolHandlerClassName ("org.apache.coyote.ajp.AjpProtocol"); } else if (protocol != null) { setProtocolHandlerClassName(protocol); } } }
所以此时会调用setProtocolHandlerClassName("org.apache.coyote.http11.Http11Protocol")从而将Connector类实例变量protocolHandlerClassName值设置为org.apache.coyote.http11.Http11Protocol,接下来在Connector的构造方法中就会根据protocolHandlerClassName变量的值产生一个org.apache.coyote.http11.Http11Protocol对象,并将该对象赋值给Connector类的实例变量protocolHandler。在Http11Protocol类的构造方法中会产生一个org.apache.tomcat.util.net.JIoEndpoint对象:
public Http11Protocol() { endpoint = new JIoEndpoint(); cHandler = new Http11ConnectionHandler(this); ((JIoEndpoint) endpoint).setHandler(cHandler); setSoLinger(Constants.DEFAULT_CONNECTION_LINGER); setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT); setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY); }
几个相关对象的构造方法调用时序图如下所示,其中org.apache.coyote.AbstractProtocol是org.apache.coyote.http11.Http11Protocol的父类org.apache.tomcat.util.net.AbstractEndpoint是org.apache.tomcat.util.net.JIoEndpoint的父类。
接下来容器启动各组件时会调用org.apache.catalina.connector.Connector的start方法,如前面分析Tomcat启动时所述,此时会调用org.apache.catalina.connector.Connector类的startInternal方法:
protected void startInternal() throws LifecycleException { // Validate settings before starting if (getPort() < 0) { throw new LifecycleException(sm.getString( "coyoteConnector.invalidPort", Integer.valueOf(getPort()))); } setState(LifecycleState.STARTING); try { protocolHandler.start(); } catch (Exception e) { String errPrefix = ""; if(this.service != null) { errPrefix += "service.getName(): \"" + this.service.getName() + "\"; "; } throw new LifecycleException (errPrefix + " " + sm.getString ("coyoteConnector.protocolHandlerStartFailed"), e); } mapperListener.start(); }
在第12行,将会调用实例变量protocolHandler的start方法。在上面分析Connector类的构造函数时发现protocolHandler变量的值就是org.apache.coyote.http11.Http11Protocol对象,所以此时将会调用该类的start方法。在Http11Protocol类中没有定义start方法,这里将会调用其父类org.apache.coyote.AbstractProtocol中的start方法:
public void start() throws Exception { if (getLog().isInfoEnabled()) getLog().info(sm.getString("abstractProtocolHandler.start", getName())); try { endpoint.start(); } catch (Exception ex) { getLog().error(sm.getString("abstractProtocolHandler.startError", getName()), ex); throw ex; } }
这里会调用endpoint对象的start方法,而endpoint是org.apache.tomcat.util.net.JIoEndpoint类的实例(在上面讲Http11Protocol类的构造方法时所提到),这里最终会执行该类的startInternal方法:
@Override public void startInternal() throws Exception { if (!running) { running = true; paused = false; // Create worker collection if (getExecutor() == null) { createExecutor(); } initializeConnectionLatch(); startAcceptorThreads(); // Start async timeout thread Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout"); timeoutThread.setPriority(threadPriority); timeoutThread.setDaemon(true); timeoutThread.start(); } }
正是在这里产生并启动本文开头提到的http-bio-8080-Acceptor-0和http-bio-8080-AsyncTimeout两个线程。第17到22行就是产生和启动http-bio-8080-AsyncTimeout线程,第15行,这里调用父类org.apache.tomcat.util.net.AbstractEndpoint的startAcceptorThreads方法:
protected final void startAcceptorThreads() { int count = getAcceptorThreadCount(); acceptors = new Acceptor[count]; for (int i = 0; i < count; i++) { acceptors[i] = createAcceptor(); String threadName = getName() + "-Acceptor-" + i; acceptors[i].setThreadName(threadName); Thread t = new Thread(acceptors[i], threadName); t.setPriority(getAcceptorThreadPriority()); t.setDaemon(getDaemon()); t.start(); } } /** * Hook to allow Endpoints to provide a specific Acceptor implementation. */ protected abstract Acceptor createAcceptor();
在这里将产生和启动http-bio-8080-Acceptor-0线程。注意在构造该线程时第6行将会调用第20行的抽象方法,该方法的具体实现是在JIoEndpoint类中:
@Override protected AbstractEndpoint.Acceptor createAcceptor() { return new Acceptor(); }
以上便是本文开头所述的两个后台线程产生和启动的流程,其相关类调用的时序图如下图所示:
同理,ajp-bio-8009-Acceptor-0和ajp-bio-8009-AsyncTimeout两个守护线程的产生和启动方式也是一致的,不再赘述。
相关推荐
tomcat中server配置文件的结构,以及处理一个http请求的全过程
在处理请求时,Tomcat会从一个预先创建的线程池中取出线程来执行Servlet的service方法。这个线程池通常被称为" Coyote Connector ",负责接收并处理来自HTTP连接器的请求。 2. **线程池管理** 在Tomcat 5.5.17版本...
在J2EE开发过程中经常由于内存溢出等多方面原因,导致tomcat服务器软件自动停止服务,从而影响了Web服务,本代码采用VB开发,主要是监控tomcat是否被关闭,保证tomcat的正常运行!
对于每个接收到的请求,Tomcat会从线程池中取出一个空闲线程来处理。线程会读取Socket中的剩余数据,解析请求,执行相应的Servlet或JSP,然后将结果写回Socket,最后关闭Socket连接。在这个过程中,线程池管理着线程...
通过对Tomcat请求处理流程中各个组件的解析,我们可以更深入地理解Tomcat的工作原理。这种基于UML序列图的描述方式不仅能够清晰地展现各个组件之间的交互关系,还能够帮助开发者更好地理解Tomcat的架构设计思想。这...
Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用服务器标准,尤其是Servlet和JSP规范。源码下载是开发者深入理解其内部工作原理的重要途径,本篇文章将围绕Tomcat7源码进行详细探讨。 一...
开发者可以通过阅读源码了解Tomcat如何处理请求,如何调度线程,以及如何优化内存和网络资源的使用。 至于“工具”标签,`Connector`类的配置和管理通常在Tomcat的`server.xml`配置文件中进行。这里可以设置端口号...
3. NIO(非阻塞I/O)改进:Tomcat 7增强了NIO连接器,提高了服务器处理并发请求的能力,提升了性能。 4. 配置简化:引入了web.xml的注解配置,使得部署描述符的编写更为简洁。 5. 新的安全特性:增加了Secure ...
Tomcat 8是在2013年推出的,它是Tomcat历史上最大的一次更新。这个版本引入了Servlet 3.1、JSP 2.3和EL 3.0等新规范,增加了对WebSocket的支持,使得实时通信变得更加便捷。此外,Tomcat 8在性能和安全性上都有所...
指定了当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数。 三、Tomcat7 的 JVM 内存使用情况 Tomcat7 的 JVM 内存使用情况可以通过访问 http://localhost:8080/manager/status 来查看。...
在Web开发中,Tomcat作为一个流行的Java应用服务器,经常被用来托管Servlet和JSP应用程序。在HTTP协议中,GET和POST请求是两种最基本的方法,它们用于客户端(通常是浏览器)向服务器发送数据。理解这两者之间的差异...
本文将围绕“Tomcat7性能优化”这一主题,详细介绍如何通过优化配置提高Tomcat服务器的并发能力,并深入探讨服务器资源(如CPU、内存、硬盘等)对处理能力的影响。 #### 二、理解服务器资源的重要性 在优化Tomcat...
12. Tomcat 7还改进了对异步处理的支持,帮助开发者处理耗时的请求,而不阻塞服务器线程。 从书籍的版权和出版信息来看,Apache Tomcat 7的出版代表着当时对Web应用程序开发的关注和重视,它致力于提供一本深入、...
要实现在Tomcat启动时自动执行的Servlet,我们需要在Servlet的`init()`方法中添加代码来创建一个后台线程。`init()`方法是Servlet生命周期中的初始化阶段,当Servlet被加载时,Tomcat会调用这个方法。我们可以在`...
1. **Servlet 3.0**:这个版本引入了异步处理能力,允许Servlet在不阻塞线程的情况下处理请求,提高了服务器的并发性能。同时,它还支持注解配置,使得Servlet、Filter和Listener的配置更为简洁。 2. **Jasper增强*...
3-5Tomcat响应请求源码与nio处理请求源码实现.mp4
此外,它还增强了异步处理能力,提升了多线程处理性能。对于Eclipse用户,可以通过Eclipse的Servers视图来配置和管理Tomcat 8实例。 Tomcat 8.5是在8的基础上进行的小幅更新,主要亮点是增加了对TLS协议的扩展支持...
【Tomcat7性能调优】是一项关键的任务,它关乎服务器的稳定性和响应速度。Tomcat作为流行的Java应用服务器,其性能优化能显著提升应用程序的运行效率。本文将深入探讨如何针对Tomcat7进行调优。 首先,我们关注的是...
Apache Tomcat 7是Apache软件基金会的一个开源项目,专门用于实现Java Servlet和JavaServer Pages(JSP)技术的标准,以及Java EE的Web应用程序部署。这个最新版本,即7.0.109,包含了对先前版本的改进和修复,旨在...
3. **线程模型**: Tomcat使用多线程处理并发请求,源代码中展示了线程池的设计和管理,包括工作线程的创建、任务调度以及线程同步机制。 4. **连接器(Connector)和引擎(Engine)**: 连接器是Tomcat接收和处理...