`
yjhexy
  • 浏览: 332268 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

tomcat HTTP处理—— Request的生命历程和相应Connector配置解析

阅读更多

Request的生命历程,可以参见常量类org.apache.coyote.Constants.java

    // Request states
    public static final int STAGE_NEW = 0;
    public static final int STAGE_PARSE = 1;
    public static final int STAGE_PREPARE = 2;
    public static final int STAGE_SERVICE = 3;
    public static final int STAGE_ENDINPUT = 4;
    public static final int STAGE_ENDOUTPUT = 5;
    public static final int STAGE_KEEPALIVE = 6;
    public static final int STAGE_ENDED = 7;

 

和用到这些常量的地方 Http11Processor.java (代码贴的比较多,可以用浏览器的 查找功能来查找上面的常量)

 while (started && !error && keepAlive && !endpoint.isPaused()) {

            // Parsing the request header
            try {
                if (keptAlive) {
                    if (keepAliveTimeout > 0) {
                        socket.setSoTimeout(keepAliveTimeout);
                    }
                    else if (soTimeout > 0) {
                        socket.setSoTimeout(soTimeout);
                    }
                }
                inputBuffer.parseRequestLine();
                request.setStartTime(System.currentTimeMillis());
                keptAlive = true;
                if (disableUploadTimeout) {
                    socket.setSoTimeout(soTimeout);
                } else {
                    socket.setSoTimeout(timeout);
                }
                inputBuffer.parseHeaders();
            } catch (IOException e) {
                error = true;
                break;
            } catch (Throwable t) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("http11processor.header.parse"), t);
                }
                // 400 - Bad Request
                response.setStatus(400);
                adapter.log(request, response, 0);
                error = true;
            }

            if (!error) {
                // Setting up filters, and parse some request headers
                rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
                try {
                    prepareRequest();
                } catch (Throwable t) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString("http11processor.request.prepare"), t);
                    }
                    // 400 - Internal Server Error
                    response.setStatus(400);
                    adapter.log(request, response, 0);
                    error = true;
                }
            }

            if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
                keepAlive = false;

            // Process the request in the adapter
            if (!error) {
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    adapter.service(request, response);
                    // Handle when the response was committed before a serious
                    // error occurred.  Throwing a ServletException should both
                    // set the status to 500 and set the errorException.
                    // If we fail here, then the response is likely already
                    // committed, so we can't try and set headers.
                    if(keepAlive && !error) { // Avoid checking twice.
                        error = response.getErrorException() != null ||
                                statusDropsConnection(response.getStatus());
                    }

                } catch (InterruptedIOException e) {
                    error = true;
                } catch (Throwable t) {
                    log.error(sm.getString("http11processor.request.process"), t);
                    // 500 - Internal Server Error
                    response.setStatus(500);
                    adapter.log(request, response, 0);
                    error = true;
                }
            }

            // Finish the handling of the request
            try {
                rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
                // If we know we are closing the connection, don't drain input.
                // This way uploading a 100GB file doesn't tie up the thread 
                // if the servlet has rejected it.
                if(error)
                    inputBuffer.setSwallowInput(false);
                inputBuffer.endRequest();
            } catch (IOException e) {
                error = true;
            } catch (Throwable t) {
                log.error(sm.getString("http11processor.request.finish"), t);
                // 500 - Internal Server Error
                response.setStatus(500);
                adapter.log(request, response, 0);
                error = true;
            }
            try {
                rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
                outputBuffer.endRequest();
            } catch (IOException e) {
                error = true;
            } catch (Throwable t) {
                log.error(sm.getString("http11processor.response.finish"), t);
                error = true;
            }

            // If there was an error, make sure the request is counted as
            // and error, and update the statistics counter
            if (error) {
                response.setStatus(500);
            }
            request.updateCounters();

            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

            // Don't reset the param - we'll see it as ended. Next request
            // will reset it
            // thrA.setParam(null);
            // Next request
            inputBuffer.nextRequest();
            outputBuffer.nextRequest();

        }

        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);

        // Recycle
        inputBuffer.recycle();
        outputBuffer.recycle();
        this.socket = null;
        // Recycle ssl info
        sslSupport = null;
    }

 

 

 

Connector配置解析:

 

官方文档:

http://tomcat.apache.org/tomcat-6.0-doc/config/http.html

 

文档中讲了比较多的选项的用法,其中,我把比较重要的几个列举下:

 

maxKeepAliveRequests

在服务器关闭socket连接之前,能保持的最大请求数。

 

maxThreads

服务器的最大线程数。讲白了就是Worker的最大数目,当然如果配置开启了Executor的话,这个配置项便是没有用的。

 

这里你会不会有疑问,线程数和请求数有什么关系。根据我上一篇文章tomcat分配请求 的分析,一个Worker线程对应一个请求。

那么你会不会有更多的疑问,maxThreads如何设置得比 maxKeepAliveRequests 小会怎么办?

请看下面这段代码

Http11Processor.java

 int keepAliveLeft = maxKeepAliveRequests;
        int soTimeout = endpoint.getSoTimeout();

        // When using an executor, these values may return non-positive values
        int curThreads = endpoint.getCurrentThreadsBusy();
        int maxThreads = endpoint.getMaxThreads();
        if (curThreads > 0 && maxThreads > 0) {
            // Only auto-disable keep-alive if the current thread usage % can be
            // calculated correctly
            if ((curThreads*100)/maxThreads > 75) {
                keepAliveLeft = 1; // 当前使用线程是最大线程数的75%的时候,会自动禁用keepAlive
            }
        }

 

 while (started && !error && keepAlive) {
……
  if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
                keepAlive = false;
……
}

 

当前使用线程是最大线程的75% 的时候,会自动禁用keepAlive

所以maxThreads设置得比maxKeepAliveRequests 小,则这个maxKeepAliveRequests 设置时没有效果的。

当maxThreads设置肯定要比 maxKeepAliveRequests 来的大,而且 maxKeepAliveRequests 不会超过maxThreads的75%!!

默认:maxThreads 为 200

maxKeepAliveRequests  为100

 

 

keepAliveTimeout

 服务器Socket读取HTTP请求行到来的限制时间。 以millionseconds为单位。默认和connectionTimeout 的值一样。

 

connectionTimeout

单位是毫秒,Connector从接受连接到提交URI请求数据的等待的时间。

开始这个我没搞懂,不过找到了这篇文章: http://twotwoandapple.blogbus.com/logs/62770043.html  上面的解释和测试。

也可以看下面的代码:Http11Processor.java

 while (started && !error && keepAlive) {
            // Parsing the request header
            try {
                if (keptAlive) {
                    if (keepAliveTimeout > 0) {
                        socket.setSoTimeout(keepAliveTimeout);
                    }
                    else if (soTimeout > 0) {
                        socket.setSoTimeout(soTimeout);
                    }
                }
                // 服务器获取客户端请求行,这里会调用inputBuffer的read 方法,引起socket阻塞,阻塞时间超过soTimeout的话就会SocketTimeOutException
                inputBuffer.parseRequestLine();

 

 

disableUploadTimeout

是否允许在上传操作的时候给与更长的socketTimeOut时间。默认false不允许。

如果设置为true,则默认为5分钟限制,超过5分钟则会报SocketTimeOut异常。

如果要改这个时间,需要用这个Attribute: timeout 这个官方文档没有写,不知道为什么,可能不建议修改吧,因为5分钟是和apache 的httpd的时间保持一致的。

类似:

    <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" disableUploadTimeout="false" timeout="600000"/>

 

  其中HTTP 协议,最好参考下RFC的文档 结合Http11Protocal 和 Http11Processor来看比较好

分享到:
评论
2 楼 yjhexy 2010-09-21  
zjugzg 写道
>当前使用线程是最大线程的75% 的时候,会自动禁用keepAlive

>所以maxThreads设置得比maxKeepAliveRequests 小,则这个maxKeepAliveRequests 设置时没有效果的。

>当maxThreads设置肯定要比 maxKeepAliveRequests 来的大,而且 maxKeepAliveRequests 不会超过maxThreads的75%!!

>默认:maxThreads 为 200

>maxKeepAliveRequests  为100


楼主,文中这一段是不是有误呀?
当前线程大于最大线程75%时候,自动禁用keepAlive这个没错。
但是下面的推论, maxThreads跟maxKeepAliveRequests的关系我认为不太对。
maxThreads 跟maxKeepAliveRequests的设置应该没有直接的关系。那个75%的关系是当前线程跟最大线程之间的关系。

我的理解是,当当前线程超过最大线程75%时,说明系统并发有点高了,就暂时放弃对keepAlive的支持(keepAlive=1),是为了支持更多的用户。因为keepAlive会让连接被同一个用户占用比较长时间。

而当当前线程数小于最大线程数的75%时,说明系统并发不算太高,就使用keepAlive来提高Socket连接的利用效率,同一个用户的多次请求可以重用同一条连接(因为如果每个请求都要打开关闭Socket是比较低效的)。

所以我觉得, maxThreads 设置大于实际平均并发量的4/3会比较合理。(即实际平均并发量小于maxThreads的75%) 这样可以让keepAlive尽量工作。

至于maxKeepAliveRequests 设置多大,哪个值最优,这个不好说。一般默认值应该就差不多了。

以上只是我的个人理解,不一定正确,欢迎一起讨论。

感谢您的回复,我认为你说的比较正确。我当时认为
maxKeepAliveRequests 表示 最多能有多少个线程在忙 ,这个肯定是错误的
其实maxKeepAliveRequests <= 最多能有几个线程在忙。
但是:maxKeepAliveRequests< maxThreads 我想应该是无可厚非的
具体我可能需要再深入研究下。
另外,不同的应用场景可能不一定需要keepAlive。
1 楼 zjugzg 2010-09-15  
>当前使用线程是最大线程的75% 的时候,会自动禁用keepAlive

>所以maxThreads设置得比maxKeepAliveRequests 小,则这个maxKeepAliveRequests 设置时没有效果的。

>当maxThreads设置肯定要比 maxKeepAliveRequests 来的大,而且 maxKeepAliveRequests 不会超过maxThreads的75%!!

>默认:maxThreads 为 200

>maxKeepAliveRequests  为100


楼主,文中这一段是不是有误呀?
当前线程大于最大线程75%时候,自动禁用keepAlive这个没错。
但是下面的推论, maxThreads跟maxKeepAliveRequests的关系我认为不太对。
maxThreads 跟maxKeepAliveRequests的设置应该没有直接的关系。那个75%的关系是当前线程跟最大线程之间的关系。

我的理解是,当当前线程超过最大线程75%时,说明系统并发有点高了,就暂时放弃对keepAlive的支持(keepAlive=1),是为了支持更多的用户。因为keepAlive会让连接被同一个用户占用比较长时间。

而当当前线程数小于最大线程数的75%时,说明系统并发不算太高,就使用keepAlive来提高Socket连接的利用效率,同一个用户的多次请求可以重用同一条连接(因为如果每个请求都要打开关闭Socket是比较低效的)。

所以我觉得, maxThreads 设置大于实际平均并发量的4/3会比较合理。(即实际平均并发量小于maxThreads的75%) 这样可以让keepAlive尽量工作。

至于maxKeepAliveRequests 设置多大,哪个值最优,这个不好说。一般默认值应该就差不多了。

以上只是我的个人理解,不一定正确,欢迎一起讨论。

相关推荐

    解析Tomcat处理请求的类Connector<三>

    【标题】:“解析Tomcat处理请求的类Connector&lt;三&gt;” 在Java的Web服务器领域,Tomcat无疑是最为广泛使用的轻量级应用服务器之一。它以其开源、免费、高效的特点深受开发者喜爱。在这个系列的第三部分,我们将深入...

    架构解析——Tomcat

    总的来说,《架构解析——Tomcat》是一本深入了解Tomcat工作原理、配置和优化的实用书籍,对于Java Web开发人员、系统管理员以及对Web服务器技术感兴趣的人来说,具有很高的学习价值。通过深入学习,读者不仅可以...

    Tomcat6.0——压缩包下载

    【标题】"Tomcat6.0——压缩包下载"涉及的是Apache Tomcat 6.0版本的安装和使用,这是一个开源的Java Servlet容器,广泛应用于Web应用的部署和开发。Tomcat6.0是该软件的一个重要里程碑,因为它在当时的Java EE 5...

    apache-tomcat-8——Linux版

    Apache Tomcat 8是Java Servlet和JavaServer Pages (JSP)技术的...在实际操作中,还需要根据服务器的配置和应用的需求进行相应的调整和优化。了解这些知识点后,你就可以顺利地在Linux环境中运行和管理Tomcat服务器了。

    tomcat 分配请求之——socket获取请求

    如果Tomcat配置了连接器(Connector)组件,如 Coyote Connector,那么它会负责实际的Socket处理和协议解析。Coyote会解析接收到的字节流,将其转换成请求和响应对象,然后再将这些对象传递给Servlet容器进行业务...

    09_Java Web——Request&Response案例

    在"09_Java Web——Request&Response案例"这个主题中,我们聚焦于HTTP请求和响应这两个核心概念,它们是Web应用中客户端与服务器交互的基础。下面将详细阐述相关知识点。 1. **HTTP协议**:超文本传输协议(HTTP)...

    tomcat 生命周期,和事件管理—— lifeCycle & event

    2. **加载(LOADING)**:在这个阶段,Tomcat读取并解析应用的配置文件,如web.xml,设置servlet和filter等。 3. **创建(CREATED)**:容器(如Context、Wrapper或Servlet)被创建,但并未开始处理请求。 4. **...

    how tomcat works——(5)容器

    2. 请求分发:容器接收到HTTP请求后,会根据请求的目标URL找到相应的Web应用和Servlet,然后将请求传递给Servlet进行处理。 3. 容器级配置:容器可以根据需要提供全局的配置,比如全局的Filter或Listener,这些配置...

    tomcat engine,host,context的管道处理——pipeline

    通过阅读博客文章《tomcat engine,host,context的管道处理——pipeline》(链接:https://yjhexy.iteye.com/blog/670309),你可以获得更详细的信息,包括如何配置和使用Valves,以及Pipeline的高级用法。...

    tomcat源码解析

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

    tomcat request.getParameter 乱码

    ### Tomcat中request.getParameter出现乱码的问题解析及解决方法 #### 一、问题背景与现象描述 在Java Web开发过程中,经常会遇到通过`HttpServletRequest`对象的`getParameter`方法获取前端表单提交的数据时出现...

    tomcat_iis_connector工具

    标题 "tomcat_iis_connector工具" 提到的是一个用于整合IIS(Internet Information Services)、Tomcat和Apache服务器的工具,特别是在Windows Server环境下。这个工具的主要目的是实现这些不同Web服务器之间的协同...

    apache & tomcat 负载均衡配置文件和tomcat connector

    本人电脑上已经配置好的相关配置文件 包括: tomcat-connectors-1.2.40-windows-x86_64-httpd-2.4.x.zip httpd.conf server.xml(tomcat) mod_jk.conf uriworkermap.properties vhosts.conf workers.properties

    tomcat及其配置文件

    Tomcat的运行离不开Java Development Kit(JDK),因为Tomcat需要JDK中的Java运行环境来解析和执行Servlet。因此,在安装和配置Tomcat之前,首先需要确保系统上已经安装了与Tomcat版本兼容的JDK。 Tomcat的核心配置...

    tomcat 类加载机制 —— ClassLoader

    《Tomcat类加载机制——ClassLoader详解》 在Java Web开发中,Tomcat作为最常用的Servlet容器,其类加载机制对于理解和优化应用性能至关重要。本文将深入探讨Tomcat的ClassLoader是如何工作的,以及它如何影响到...

    tomcat_iis_connector

    标题中的“tomcat_iis_connector”指的是Tomcat与IIS之间的连接器,它允许IIS(Internet Information Services)和Tomcat应用服务器进行交互,实现两者之间的集成。在Web服务器领域,IIS是微软公司推出的一款强大的...

    Tomcat中的Connector配置讲解

    了解和正确配置Tomcat的Connector组件对于提升Tomcat服务器的性能和稳定性至关重要。 Connector组件可以支持不同的协议,包括HTTP/1.1、AJP等。其中HTTP/1.1 Connector是处理Web请求的主要协议。它不仅能处理...

    Tomcat集群——使用MSM管理集群Session

    【标题】:“Tomcat集群——使用MSM管理集群Session” 在分布式系统中,尤其是在基于Java的Web应用中,实现session的共享是确保用户状态在不同服务器之间无缝切换的关键。Tomcat,作为流行的开源Servlet容器,提供...

Global site tag (gtag.js) - Google Analytics