`

How Tomcat Works 读书笔记(第四章)

阅读更多

     Tomcat的连接器是一个单独的模块,它可以插入到一个servlet容器里面,现在一些比较常见的连接器有Coyote,mod_jk, mod_jk2,和mod_webapp.一个Tomcat的连接器必须要满足下面的要求:
1. 它必须实现org.apache.catalina.Connector接口
2. 它必须要创建一个实现org.apache.catalina.Request对象的request
3. 它必须要创建一个实现org.apache.catalina.Response对象的response
     Tomcat 4的连接器和第三章的差不多,它也是等待HTTP请求,创建reqeust和response对象,而后把request和response对象传给container容器。它是调用container的invoker方法来实现传递的:

Public void invoke (org.apache.catalina.Reqeust request, org.apache.catalina.Response response);


    在invoke方法里面,container加载servlet类,调用它的service方法,管理session,并使用log等组件。这个connector对第三章的connector做了一些优化,第一点就是提供了一个池,避免了对象创建的开销,第二点,在很多地方用char数组代替了string。
    HTTP 1.1 新特性:
    1. 持久连接:这个我们比较熟悉,就是复用Connection,来下载多个资源;
    2. 块编码: 在content-length没有准备好的情况下,每块数据都会提供一个length,     用来指示块长度;
    3. 100状态码的使用, 这个一般用作client来确定服务器状态用的,这个一般用作客户端准备传送一个大的request body,但无法确定服务器是否接受它,如果服务器此刻是down的,那么客户端传送一个大的request body是一个资源浪费。
    Connector接口:
1. Tomcat的连接器都是实现org.apache.catalina.Connector接口,它的主要的方法是getContainer, setContainer, createRequest,createResponse. setContainer会使一个Connector和一个Container联系起来,其他的createRequest和createResponse比较容易理解,就是创建一个Request和Response对象。
2. Org.apache.catalina.http.HttpConnector是它的实现类。下面我们看一下类图:



我们来看HttpConnector类 的实现吧:
      首先在它的open方法里面调用ServerSocketFactory创建一个ServerSocket,DefaultServerSocketFactory实现ServerSocketFactory,这个很好理解,就是创建一个ServerSocket。
      在第三章里面,我们的HttpConnector只有一个HttpProcessor实例,它一次只能请求一个Http请求,在Tomcat连接器里面,它有一个HttpProcessor对象池,每个HttpProcessor都在独自的线程里面运行,所以HttpProcessor可以同时处理多个Http请求。
      HttpConnector维护了一个HttpProcessor池来避免HttpProcessor的创建, HttpProcessor实例是维护在一个栈中的,
      Private Stack processors = new Stack();
      在HttpConnector中有个minProcessors和maxProcessors两个变量,HttpConnector会创建minProcessors个HttpProcessor,它会创建HtttpProcessor,直到maxProcessors达到后。 变量curProcessor保存着HttpProcessor创建的数量。
在HttpConnector的start方法里面会调用下面的代码来创建初始的Processor。

      While(curProcessors < minProcessors) {
	If( maxProcessors > 0 && curProcessor >= maxProcessors){
		Break;
}
HttpProcessor processor = newProcessor();
Recycle(processor);
}


      Recycle方法是将HttpProcessor压入到栈中去的。
      HttpProcessor是负责解析HTTP Request请求头和Header的,一个HttpProcessor和一个request和一个response对象关联。 在HttpProcessor的构造函数里面会调用createRequest和createResponse方法来创建Request对象和Response对象。
       当有一个请求来临时,HttpProcessor会从对象池中取得一个HttpProcessor对象,如果到达maxProcessors的时候,HttpConnector直接关闭socket,Http request将不会被处理。获得一个HttpProcessor方法后,将会调用HttpProcessor的assign方法:
      Processor.assing(socket);
      HttpProcessor对象是利用SocketInputStream读取请求头,解析Http Request。我们现在就来看一下assign方法吧。

 /**
     * Process an incoming TCP/IP connection on the specified socket.  Any
     * exception that occurs during processing must be logged and swallowed.
     * <b>NOTE</b>:  This method is called from our Connector's thread.  We
     * must assign it to our own thread so that multiple simultaneous
     * requests can be handled.
     *
     * @param socket TCP socket to process
     */
    synchronized void assign(Socket socket) {

        // Wait for the Processor to get the previous Socket
        // 在创建的时候,available是false的,所以这个while循环将被跳过
        while (available) { 
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        // Store the newly available Socket and notify our thread
        // 我们将available设置成true,调用notifyAll来唤醒等待当前对象的锁
        this.socket = socket;
        available = true;
        notifyAll();

        if ((debug >= 1) && (socket != null))
            log(" An incoming request is being assigned");
        // 这个方法就可以返回了,HttpConnector就可以相应下一个请求了。

    }



     对了,我们要完全理解这个HttpProcessor线程,我们应该先看一下HttpConnector的newProcessor方法。

/**
     * Create and return a new processor suitable for processing HTTP
     * requests and returning the corresponding responses.
     */
    private HttpProcessor newProcessor() {

        //        if (debug >= 2)
        //            log("newProcessor: Creating new processor");
        // 首先会创建一个HttpProcessor对象
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                // 在这里调用了processor的start方法
                ((Lifecycle) processor).start();
            } catch (LifecycleException e) {
                log("newProcessor", e);
                return (null);
            }
        }
        created.addElement(processor);
        return (processor);
    }


    其实HttpProcessor的构造函数很简单,主要会调用HttpConnector的createRequest和createResponse方法。
    我们看到在创建HttpProcessor的时候会调用start方法,在start方法里面调用threadStart方法,在start线程里面将该线程设置成守护线程,然后调用start方法,实际上会执行现场的run方法,我们就重点看一下run方法吧。其实run方法很简单,就是得到一个socket,然后处理该socket,处理完毕之后调用HttpConnector的recycle方法,将该对象压入processors栈中。

/**
     * The background thread that listens for incoming TCP/IP connections and
     * hands them off to an appropriate processor.
     */
    public void run() {

        // Process requests until we receive a shutdown signal
        while (!stopped) {

            // Wait for the next socket to be assigned
            Socket socket = await();
            if (socket == null)
                continue;

            // Process the request from this socket
            try {
                process(socket);
            } catch (Throwable t) {
                log("process.invoke", t);
            }

            // Finish up this request
            connector.recycle(this);

        }

        // Tell threadStop() we have shut ourselves down successfully
        synchronized (threadSync) {
            threadSync.notifyAll();
        }

    }


     下面最重要的就是await方法了,这个方法写的很巧妙。我们来看一下吧:

/**
     * Await a newly assigned Socket from our Connector, or <code>null</code>
     * if we are supposed to shut down.
     */
    private synchronized Socket await() {

        // 在初始化的时候availabe是false,所以会调用wait方法
        // Wait for the Connector to provide a new Socket
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }

        // 其实我们刚才也看到了,调用了assign方法后,available的值会变成true,
        // 然后将socket返回,我们可以看到在这里将socket赋给了一个局部变量
        // 这一点非常高明,使得HttpProcessor可以复用了。
        // Notify the Connector that we have received this Socket
        Socket socket = this.socket;
        available = false;
        notifyAll();

        if ((debug >= 1) && (socket != null))
            log("  The incoming request has been awaited");

        return (socket);

    }


  • 大小: 34.9 KB
1
0
分享到:
评论

相关推荐

    How Tomcat Works 读书笔记(第三章)

    《How Tomcat Works》这本书是理解Apache Tomcat服务器工作原理的重要资源,第三章主要探讨了Tomcat的架构和核心组件。以下是对这部分内容的详细解读: Tomcat作为一款开源的Java Servlet容器,其核心功能是解析...

    java版五子棋源码-HowTomcatWorks:HowTomcatWorks读书笔记

    java版五子棋源码HowTomcatWorks 《How Tomcat Works》 every chapter demo . Here's my ebook: Part of the UML diagram is as follows. 1.The default connector class diagram: 2.The class diagram of ...

    学习tomcat源码+英文《How Tomcat Work》和每一章的相关项目+tomcat6源码依赖jar

    《How Tomcat Works》是一本经典的书籍,详细解释了Tomcat的工作原理,对于理解其内部机制非常有帮助。 Tomcat的核心功能可以分为几个主要部分: 1. **Catalina**:这是Tomcat的主要组件,负责Servlet和JSP的处理...

    How-Tomcat-Works-中文版笔记

    《How Tomcat Works》中文版笔记详细介绍了Apache Tomcat的内部架构和运行机制,Tomcat是一个广泛使用的Java开源Web服务器和Servlet容器,它为处理基于Java的Web应用提供平台。本书不仅深入分析了Tomcat的核心组件和...

    HowTomcatWorks:《深度剖析Tomcat》原始码及笔记

    第四章Tomcat的默认连接器 第五章servlet容器 第六章生命周期 第七章日志记录器 第八章加载器 第九章会议管理 第十章应用程序 第十一章StandardWrapper 第十二章StandardContext 第十三章主机和引擎 第十四章服务器...

    Tomcat源码研究.pdf

    #### 1.14《How Tomcat Works》读书笔记(四):容器初探 - **容器概念**:Container是Tomcat中的核心组件之一,负责管理Web应用程序及其资源。 - **层级关系**:容器按照层次结构组织,包括Engine、Host、Context...

    tomcat源码分析

    8. **《How Tomcat Works》读书笔记** 这一系列笔记详细介绍了Tomcat的工作原理,包括Connector如何处理网络连接,Container如何管理Servlet,以及默认的Connector和容器配置。通过阅读这些笔记,可以深入理解...

    Tomcat_学习

    《How Tomcat Works》这本书是理解Tomcat工作原理的重要参考资料。书中详细介绍了Tomcat如何处理HTTP请求,如何加载和执行Servlet,以及它是如何管理线程和内存的。通过阅读这本书,你可以深入理解Tomcat的内部架构...

    SomeJava:将以往项目应用中各种框架、中间件的使用方式抽取出来,希望以后给刚接触直接运行,入门参考。。

    tomcat-work 是《How Tomcat Works》的代码,可惜是Jdk1.4的,也可以作为学习用。 ###分布式小框架Demo gh-soa 作为服务端 gh-soa-remote gh-web 作为客户端,通过hessian访问soa。 帮别人弄的一个框架Demo、基于...

    WebGoat笔记三_访问控制缺陷(AccessControlFlaws).pdf

    2.2.1.2 技术原理(How It works) 无 2.2.1.3 总体目标(General Goals) 每个用户都是角色的成员,每个角色只允许访问那些特定的资源。你的目标是浏览本站管理所使用的访问控制规则。 2.2.1.4 操作方法...

    java8源码-cainiao:自娱自乐

    Books中存放分布式技术学习和书籍阅读后笔记、总结和一些面试搜集的问题,具体查看Books中ReadMe.md Internet中存放分布式技术等相关的学习总结 JUC中存放系列学习内容,包括系列学习总结+优秀博文搜集等 Collection...

Global site tag (gtag.js) - Google Analytics