`
fj_ding
  • 浏览: 37176 次
社区版块
存档分类
最新评论

Tomcat连接器运行过程(源码阅读)

阅读更多

:为了单纯的了解连接器运行过程,与别的组件相关部分代码被注释了,该篇文章只是简单的对重点代码进行解释,理论知识可以参考《how tomcat works》这本书,感觉还是不错的。

1.启动(这是自己写的一个简单启动代码)

private static void start() {
HttpConnector connector = new HttpConnector();
connector.start();
    }
 

2.HttpConnecter类中的start()方法

 public void start() {
        // Validate and update our current state
        // if (started)
        // throw new
        // LifecycleException(sm.getString("httpConnector.alreadyStarted"));
        threadName = "HttpConnector[" + port + "]";
        // lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        //启动当前线程
        threadStart();

        // Create the specified minimum number of processors
        while (curProcessors < minProcessors) {
            if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
                break;
            HttpProcessor processor = newProcessor();
            //将当前线程创建处理器加入处理器池中
            recycle(processor);
        }
    }
 

3.HttpConnecter类中threadStart()方法

private void threadStart() {

        // log(sm.getString("httpConnector.starting"));
        // 启动当前的connector的线程
        thread = new Thread(this, threadName);
        // 设置为守护线程
        thread.setDaemon(true);
        thread.start();

    }
 

4.HttpConnector类的run()方法

public void run() {

        // Loop until we receive a shutdown command
        while (!stopped) {
            // Accept the next incoming connection from the server socket
            Socket socket = null;
            try {

                socket = serverSocket.accept();

                // 设置链接超时(假设设置为10分钟)以后,如果客户端socket和服务端socket链接以后10中以后会自动断开
                // tcp链接,默认是一支不设置超时就是一直链接的
                if (connectionTimeout > 0)
                    socket.setSoTimeout(connectionTimeout);
                // 决定是否使用nagle算法,也就是将小数据报先不发送,附加在下一个数据包后面发送过来
                socket.setTcpNoDelay(tcpNoDelay);
            } catch (AccessControlException ace) {
                log("socket accept security exception", ace);
                continue;
            } catch (IOException e) {

                try {
                    // If reopening fails, exit
                    synchronized (threadSync) {
                        if (started && !stopped)
                            log("accept error: ", e);
                        if (!stopped) {

                            serverSocket.close();
                            // if (debug >= 3)
                            // log("run: Reopening server socket");
                            // serverSocket = open();
                        }
                    }

                } catch (IOException ioe) {
                    log("socket reopen, io problem: ", ioe);
                    break;
                } catch (KeyStoreException kse) {
                    log("socket reopen, keystore problem: ", kse);
                    break;
                } catch (NoSuchAlgorithmException nsae) {
                    log("socket reopen, keystore algorithm problem: ", nsae);
                    break;
                } catch (CertificateException ce) {
                    log("socket reopen, certificate problem: ", ce);
                    break;
                } catch (UnrecoverableKeyException uke) {
                    log("socket reopen, unrecoverable key: ", uke);
                    break;
                } catch (KeyManagementException kme) {
                    log("socket reopen, key management problem: ", kme);
                    break;
                }

                continue;
            }

            // Hand this socket off to an appropriate processor
            // 启动完一个proccessor线程以后,先让它们处于wait状态,因为此时并没有需要处理的请求。
            HttpProcessor processor = createProcessor();
            if (processor == null) {
                try {
                    // log(sm.getString("httpConnector.noProcessor"));
                    socket.close();
                } catch (IOException e) {
                    ;
                }
                continue;
            }
            // 将tcp连接封装的socket对象分配给Processor处理
            processor.assign(socket);

            // The processor will recycle itself when it finishes
            synchronized (threadSync) {
                threadSync.notifyAll();
            }
        }
    }
 

5.HttpConnector类的assign()方法

synchronized void assign(Socket socket) {


            // Wait for the Processor to get the previous Socket,默认为false
            while (available) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }

            // Store the newly available Socket and notify our thread
            this.socket = socket;
            //通知processor的线程现在可以启动了
            available = true;
            //通知自己的在等待的线程可以激活了,他们会自己去竞争资源
            //因为是用当前processor的对象来进行wait的(),因此就是通知当前processor的线程运行,而不是所有
            //在等待processor线程
            notifyAll();

            if ((debug >= 1) && (socket != null))
                log(" An incoming request is being assigned");

        }
  

接下来看看与处理器创建相关代码,因为一个连接器中有可以有多个处理器,因此查看各个处理器创建的过程是很有必要的,这里的多个处理器采用的是处理器池是实现的,跟dbcp数据库连接池的实现方式很相似,接下来看代码


6.httpConnector中createProcessor()方法
注,其中processors的声明是这样的:

private Stack<Object> processors = new Stack<Object>();
private HttpProcessor createProcessor() {

        synchronized (processors) {
            // 池中有处理器可用
            if (processors.size() > 0) {

                return ((HttpProcessor) processors.pop());
            }
            // 如果处理器池中没有可以用的处理器,则判断当前的处理器个数(此时池中是空的)是否大于设置最大处理器个数,

            if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {
                // 没有则创建
                return (newProcessor());
            } else {
                // 如果处理器最大个数被设置为-1,则要多少个处理器就创建多少个,不受限制
                if (maxProcessors < 0) {

                    return (newProcessor());

                } else {

                    return (null);
                }
            }
        }
    }
 

7.httpConnector中newProcessor()方法

private HttpProcessor newProcessor() {

        // 当创建一个处理器,则当前处理器标记加1,给改处理器设置了个名字,线程也是这么做的
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                // 在HttpProcessor类中的start方法里启动processor线程(没创建一个处理器就马上启动,但是启动万以后并没有让processor的run方法马上执行,而是出于wait状态)
                ((Lifecycle) processor).start();
            } catch (Exception e) {
                log("newProcessor", e);
                return (null);
            }
        }
        created.addElement(processor);
        return (processor);

    }
 

接下来我们看看HttpProcessor中相关代码
1.HttpProcessor中start()方法

// 基本上都是用在start方法中启动自己的线程的。
    public void start() // throws LifecycleException
    {

        // if (started)
        // throw new LifecycleException
        // (sm.getString("httpProcessor.alreadyStarted"));
        // lifecycle.fireLifecycleEvent(START_EVENT, null);
        // started = true;

        threadStart();

    }
 

2.HttpProcessor中start()方法

 private void threadStart() {

            //log(sm.getString("httpProcessor.starting"));

            thread = new Thread(this, threadName);
            //设置为守护线程,因为tomcat是为web应用程序服务的,所以他的线程一般都是守护线程
            //同时,在守护线程中创建的线程即使不setDaemon,也是守护线程
            thread.setDaemon(true);
            //开启processor中的run方法。
            thread.start();

            if (debug >= 1)
                log(" Background thread has been started");

        }
 

3.HttpProcessor中run()方法

public void run() {

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

            //当前线程等待下一个socket来以后激活所有的等等的线程(就是处理器创建以后不马上执行完,而是出于wait状态等待socket来以后并被别的线程激活)
            Socket socket = await();
            if (socket == null)
                continue;

            // Process the request from this socket
            try {
            //该方法就是处理socket,用户解析http头,创建request和response对象(以后会单独详细讲)
                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();
        }
        }

4.HttpProcessor中await()方法

 private synchronized Socket await() {

        // Wait for the Connector to provide a new Socket
        while (!available) {
            try {
            //就是调用当前对象的wait()方法
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
 

5.HttpProcessor中process()方法

public void process(Socket socket)
{
//该方法是处理http头和内容的,接下来会详细讲
}
 

到此,tomcat中连接器的运行过程基本结束了,怎么处理socket会在之后详细讲

 

分享到:
评论

相关推荐

    Tomcat深入剖析pdf+源码(Tomcat运行原理)

    6. **连接器与管道**:Coyote连接器负责接收和发送网络数据,管道(Pipeline)则提供了灵活的处理链,允许自定义处理器(Valve)来扩展Tomcat的功能。 7. **部署与热部署**:Tomcat支持自动部署和热部署,只需将WAR...

    Tomcat8 源码,可以在eclipse中直接运行

    通过运行源码,我们可以观察到Tomcat的启动过程,这涉及到加载配置、初始化各种组件、注册Servlet和过滤器、以及启动监听器。同时,也可以设置断点,逐步调试,深入理解Tomcat如何处理HTTP请求,如何调用Servlet,...

    tomcat7源码

    源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的学习能够帮助我们更深入地理解Web应用的部署、运行以及性能优化。 首先,我们要了解Tomcat的架构。Tomcat7基于...

    tomcat源码

    本篇文章将深入探讨Tomcat的工作原理,并结合源码进行解析,帮助读者更全面地理解这款服务器的运行机制。 1. **Tomcat架构概述** Tomcat的设计遵循了Servlet容器的基本规范,主要包括四个核心组件:Catalina(核心...

    tomcat的连接器最新版

    至于文件`tomcat-connectors-1.2.48-src`,这看起来是Tomcat连接器源码的版本,对于开发者来说,研究源码有助于深入理解Tomcat的工作原理,定制连接器功能,或者为Tomcat贡献代码。 总之,Tomcat的连接器是其核心...

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

    源码是软件的基石,通过阅读源码,我们可以了解到Tomcat如何处理HTTP请求,如何管理线程,以及如何部署和运行Web应用。Tomcat的源码主要分为几个核心模块: 1. **Catalina**:这是Tomcat的核心组件,负责Servlet...

    tomcat7源码下载

    Tomcat采用NIO(非阻塞I/O)或BIO(阻塞I/O)模型,Coyote连接器负责这部分实现。NIO模型在高并发环境下表现出色,因为它可以处理大量并发连接,而无需为每个连接创建新线程。 四、Tomcat7的部署与管理 Tomcat7...

    tomcat6的源码

    7. **连接器(Connector)**:Tomcat支持多种协议,如HTTP/1.1、AJP等。`Coyote`组件负责处理这些协议,其中` CoyoteConnector`是核心部分。 8. **JSP和 Jasper**:Tomcat内置了JSP引擎Jasper,负责编译JSP页面为...

    tomcat8源码

    5. **连接器(Connector)与协议处理器(Protocol Handler)** - **Coyote Connector**:Tomcat的Coyote组件负责接收和发送网络数据。它提供了两个协议处理器,JKoyote HTTP/1.1和APR(Apache Portable Runtime)...

    tomcat6,7源码

    再者,Tomcat的连接器(Connector)是处理网络通信的关键部分。在`tomcat-connectors-1.2.37-src.zip`中,我们可以看到对HTTP/1.1协议的支持,包括解析请求、建立响应和管理线程池等。连接器的源码提供了如何实现...

    apache-tomcat-7.0.81-src 源码免费下载

    3. **连接器(Connector)**:Tomcat通过连接器与外部世界通信。`connector`目录下的源码展示了如何配置和管理不同的连接器,如基于HTTP/1.1的 Coyote 连接器。 4. **生命周期管理**:在`common`和`shared`目录中,...

    apache-tomcat-9.0.14-src源码

    Tomcat有多种连接器实现,如 Coyote 和 APR(Apache Portable Runtime),它们在不同的网络协议和性能需求下提供服务。 3. **Jasper**:Jasper是Tomcat中用于处理JSP的组件。它将JSP转换为Java Servlet,然后编译成...

    Tomcat6 编译好的源码

    通过阅读和分析源码,开发者可以学习到如何实现一个高效的Servlet容器,如何处理HTTP请求,以及Tomcat是如何管理Web应用程序的部署和运行的。 【压缩包子文件的文件名称列表】"tomcat6-master"可能表示这是Tomcat6...

    tomcat8.0源码

    - `server.xml`:这是Tomcat的主要配置文件,包含了服务、主机、上下文和连接器的配置。 - `web.xml`:每个Web应用都有一个web.xml,它是应用的部署描述符,定义了Servlet、过滤器、监听器等元素。 4. **生命周期...

    How Tomcat Works 中文版+例程源码

    源码分析部分可能包括Tomcat的启动过程、请求处理流程、线程池管理、容器结构实现以及特定Servlet的生命周期管理等方面。通过阅读源码,开发者可以深入理解Tomcat如何处理网络请求,如何调度线程,以及如何管理和...

    tomcat源码解析

    - **第3章**:详细解析了Tomcat中的连接器(Connector)组件,它是Tomcat与客户端进行通信的关键部分。 - **第4章**:深入探讨了Tomcat的默认连接器的实现细节,包括HTTP/1.1的新特性及其对连接器的影响。 - **第5章...

    我的tomcat7源码手撕过程

    ### Tomcat7源码手撕过程详解 #### Tomcat初始化流程分析 Tomcat是一个流行的Java Servlet容器,用于部署和运行Web应用程序。理解Tomcat的工作原理对于优化应用性能、解决部署问题至关重要。以下是对Tomcat7启动...

    Tomcat6的源码

    【描述】"Tomcat6的可运行Java源码代码,注意可以运行的哦,只需导入即可"表明这个源码包不仅包含源代码,而且是可运行状态,这意味着开发者可以直接在开发环境中导入这些源码,进行调试、学习或定制化修改。Tomcat6...

    apache-tomcat-9.0.8-src源码资源

    Tomcat通过不同的连接器(如HTTP、AJP)与网络通信。`org.apache.coyote`包下包含这些连接器的实现,例如` CoyoteAdapter`、`Http11NioProtocol`等。 5. **部署与生命周期管理**: Tomcat提供自动部署和管理Web...

Global site tag (gtag.js) - Google Analytics