`
xupo
  • 浏览: 215729 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Tomcat源码之AprEndpoint

 
阅读更多
APR,全称Apache Portable Runtime,使用native server为Tomcat提供更好的伸缩性、更高的性能以及更强的集成能力。APR还是Apache HTTP Server2.x中的核心轻量级库,它可以提供更好的IO功能(如sendfile,epoll和OpenSSL)、OS功能和本地线程管理(共享内存、NT管道和UNIX套接字)。这些都可以使Tomcat变得更通用、更易扩展。
APR运行需要以下3个组件:APR Library、JNI Wapper for APR和OpenSSL Libary。如果以上功能已经安装,Tomcat在启动时会自动使用APR Connector。
与JIoEndPoint相比,AprEndpoint使用JNI的接口来获得对Socket的访问,功能实现要更为复杂,含有的线程更多:Acceptor Thread、Asynctimeout Thread、Poller Thread、Comet Poller Thread和Sendfile Thread。

Acceptor Thread、Asynctimeout Thread
功能与JIoEndpoint中的类似,同样是完成侦听和监控request的任务,不同的是这两个class直接继承Thread而不是实现Runnable接口。最终负责处理Socket的地方是在AjpConnectionHandler中,对应的处理线程(池)是Exector。
  
    protected class Acceptor extends Thread {
.....
    @Override
        public void run() {
            int errorDelay = 0;
            // Loop until we receive a shutdown command
            while (running) {
                ....
                try {
                    //if we have reached max connections, wait
                    awaitConnection();
                  
                    long socket = 0;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        socket = Socket.accept(serverSock);
                    } catch (Exception e) {
                        // Introduce delay if necessary
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        // re-throw
                        throw e;
                    }
                    // Successful accept, reset the error delay
                    errorDelay = 0;
                    //increment socket count
                    countUpConnection();
                    .....
                } catch (Throwable t) {
                    ....
                }
                }
                // The processor will recycle itself when it finishes
            }
        }
    }

  
    protected class AsyncTimeout implements Runnable {
      
        @Override
        public void run() {
            // Loop until we receive a shutdown command
            while (running) {
                ....
            long now = System.currentTimeMillis();
                Iterator<SocketWrapper<Long>> sockets =
                    waitingRequests.iterator();
                while (sockets.hasNext()) {
                    SocketWrapper<Long> socket = sockets.next();
                    if (socket.async) {
                        long access = socket.getLastAccess();
                        if ((now-access)>socket.getTimeout()) {
                            processSocketAsync(socket,SocketStatus.TIMEOUT);
                        }
                    }
                }
             ....                }
            }
        }
    }

Poller Thread
Poller类主要负责poll传入的socket连接(提供add(),由其他线程传入),如果发现有事件,交给AjpConnectionHandler处理。
    public class Poller extends Thread {
      ............
      
        public void add(long socket) {
            synchronized (this) {
                // Add socket to the list. Newly added sockets will wait
                // at most for pollTime before being polled
                if (addCount >= addS.length) {
                    // Can't do anything: close the socket right away
                    if (comet) {
                        processSocket(socket, SocketStatus.ERROR);
                    } else {
                        destroySocket(socket);
                    }
                    return;
                }
                addS[addCount] = socket;
                addCount++;
                this.notify();
            }
        }
      
        @Override
        public void run() {
         
                try {
                    // Add sockets which are waiting to the poller
                    if (addCount > 0) {
                        synchronized (this) {
                            int successCount = 0;
                            try {
                                for (int i = (addCount - 1); i >= 0; i--) {
                                    int rv = Poll.add(serverPollset, addS[i], Poll.APR_POLLIN);
                                    if (rv == Status.APR_SUCCESS) {
                                        successCount++;
                                    } else {
                                        // Can't do anything: close the socket right away
                                        if (comet) {
                                            processSocket(addS[i], SocketStatus.ERROR);
                                        } else {
                                            destroySocket(addS[i]);
                                        }
                                    }
                                }
                            } finally {
                                keepAliveCount += successCount;
                                addCount = 0;
                            }
                        }
                    }
                    maintainTime += pollTime;
                    // Pool for the specified interval
                    int rv = Poll.poll(serverPollset, pollTime, desc, true);
                    if (rv > 0) {
                        keepAliveCount -= rv;
                        for (int n = 0; n < rv; n++) {
                            // Check for failed sockets and hand this socket off to a worker
                            if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP)
                                    || ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)
                                    || (comet && (!processSocket(desc[n*2+1], SocketStatus.OPEN)))
                                    || (!comet && (!processSocket(desc[n*2+1])))) {
                                // Close socket and clear pool
                                if (comet) {
                                    processSocket(desc[n*2+1], SocketStatus.DISCONNECT);
                                } else {
                                    destroySocket(desc[n*2+1]);
                                }
                                continue;
                            }
                        }
                    }
              ..............
            } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.poll.error"), t);
                }
            }
            synchronized (this) {
                this.notifyAll();
            }
        }
    }

Sendfile Thread
用于实现sendfile功能,它的工作流程跟Poller类似,add()中,将文件写入socket中。在run()中用Poll来轮询socket的状态,处理文件写入.
代码略....

初始化和启动
在bind()中完成对socket/SSL(如果要支持的话)等资源的初始化,在startInternal(),启动Poller线程组, Comet Poller线程组(两个都是Poller类),Sendfile线程组,Acceptor线程组和1个运行AsyncTimeout接口的线程组.
分享到:
评论

相关推荐

    tomcat源码+文档pdf+源码解析

    这个资源包包含了Tomcat的源码、文档以及源码解析,对于深入理解Tomcat的工作原理、优化应用性能以及进行二次开发具有极大的帮助。 首先,让我们深入探讨Tomcat的源码。源码是软件的基石,通过阅读源码,我们可以...

    Ant编译Tomcat源码、MyEclipse导入Tomcat源码、执行Tomcat源码启动Tomcat

    例如,设置正确的JDK版本,因为Tomcat需要与之兼容的Java环境。这可以在项目属性的"Java Build Path"中进行调整。同时,由于Tomcat是一个Web服务器,你需要将其配置为MyEclipse的服务器实例。在"MyEclipse" -&gt; ...

    tomcat源码

    Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...

    tomcat源码导入myeclipse

    【标题】"Tomcat源码导入MyEclipse"是一个针对Java开发者的重要实践操作,它涉及到两个关键组件:Tomcat服务器和MyEclipse集成开发环境。Tomcat是Apache软件基金会的一个开源项目,它作为Servlet和JavaServer Pages...

    tomcat 源码分析系列文档

    4. "Tomcat源码分析(4)容器处理链接之责任链模式.doc":分析了Tomcat如何利用责任链模式来处理请求,使得请求可以被多个处理器(如过滤器)有序处理。 5. "tomcat加载类的顺序.doc":详细说明了Tomcat加载类的具体...

    编译tomcat源码所需jar包

    本文将深入探讨“编译Tomcat源码所需jar包”这一主题,帮助开发者了解如何从源码构建Tomcat,以及在这个过程中需要用到的关键jar包。 首先,我们来了解一下为什么要从源码编译Tomcat。直接下载预编译的二进制版本...

    「Tomcat源码剖析」.pdf

    Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...

    eclipse运行tomcat源码:修改源码:重新编译:重新打包

    1.tomcat源码文件 2.tomcat程序文件 3.Ant程序文件 4.tomcat源码在eclipse运行,重新编译,重新打包步骤文件 5.一个tomcat源码在eclipse上运行的java工程 作用: 1.用于学习tomcat源码和了解tomcat运行机制 2.学习...

    Tomcat源码开发环境搭建

    手把手教你搭建Tomcat7源码开发环境,如果有了如下说明还搭建不成功,建议考虑下自己的理解能力,能不能走编码这条路。附近包括Tomcat源码、Tomcat源码开发环境依赖的包、Tomcat的环境编译工具ant 1、建立如下...

    tomcat源码学习之环境搭建

    在深入探讨Tomcat源码学习之前,我们首先要理解Tomcat是什么。Tomcat是一款开源的、免费的Web服务器和Servlet容器,由Apache软件基金会维护。它实现了Java Servlet和JavaServer Pages(JSP)规范,是Java EE应用...

    IDEA版tomcat源码搭建.docx

    IDEA 版 Tomcat 源码搭建 Tomcat 是一个开源的 Web 服务器软件,由 Apache 软件基金会开发和维护。它支持众多的 Java 库和框架,能够提供高性能和高可扩展性的 Web 应用程序。IDEA 是一款功能强大的集成开发环境...

    tomcat源码依赖包

    《深入理解Tomcat源码:必备依赖包解析》 Tomcat作为一款广泛应用的开源Java Servlet容器,其源码的编译与理解对于开发者来说具有重要的价值。为了能够顺利地编译Tomcat源码,了解并掌握相关的依赖包是至关重要的。...

    tomcat7源码

    《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Servlet和JSP规范。源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的...

    tomcat源码编译所需jar包

    《深入解析Tomcat源码编译所需jar包》 Tomcat作为一款广泛应用的开源Web服务器和Servlet容器,其源码的编译与理解对于开发者来说是提升技术水平的重要途径。源码编译过程中,jar包的正确配置至关重要。本文将详细...

    tomcat8源码

    Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是开发和部署Java Web应用的重要平台。深入理解Tomcat的源码有助...

    Tomcat源码研究.pdf

    根据所提供的文件信息,我们将从以下几个方面详细探讨Tomcat源码的相关知识点: 1. Catalina脚本解析:Catalina是Tomcat的主引擎,负责整个容器的初始化和处理。在Tomcat源码中,Catalina的脚本解析是了解其启动...

    tomcat源码包

    tomcat的源码包

Global site tag (gtag.js) - Google Analytics