美文网首页
tomcat请求分析(2)Socket转换为内部请求

tomcat请求分析(2)Socket转换为内部请求

作者: 不存在的里皮 | 来源:发表于2019-04-11 06:01 被阅读0次

    参考

    http://www.iocoder.cn/Tomcat/yuliu/A-request-analysis-2-Socket-is-converted-to-an-internal-request-object/

    理解请求信息

    请求信息包括以下三条

    • 请求行(request line)
      例如GET /images/logo.gif HTTP/1.1,表示从/images目录下请求logo.gif这个文件。

    • 请求头(request header),空行
      例如Accept-Language: en

    • 其他消息体

    这里以请求行数据的解析为例,在 Http 协议中该行内容格式为:

    Request-Line = Method SP Request-URI SP HTTP-Version CRLF
    

    步骤总结

    1. Accepter接收新的socket连接后,创建SocketProcessor交给线程池运行。
    2. 后者在run内调用AbstractProtocol.AbstractConnectionHandler.process
    3. 然后进一步调用AbstractHttp11Processor.process,在此调用getInputBuffer().parseRequestLine(keptAlive)getInputBuffer().parseHeaders())来解析请求行和请求头部。
    4. InternalInputBuffer.parseRequestLinefill填充缓冲区,然后读取缓冲区来解析请求行。如果当前缓冲读完了,还不够解析,则继续调用fill读取,如下:
         do {
               // 缓冲区读完了还不够这部分解析的,需要继续读取。
               if (pos >= lastValid) {
                   if (!fill())
                       throw new EOFException(sm.getString("iib.eof.error")); // 没解析完读取流就见底了,报错
               }
               ...
               chr = buf[pos++];
           } while ((chr == Constants.CR) || (chr == Constants.LF));
      
    5. 请求头的最大长度是8192,在Http11Processor的构造函数中inputBuffer = new InternalInputBuffer(request, headerBufferSize);,提供的headerBufferSize就是最大长度。自行跟踪代码(全文搜索"ctrl+shift+f")可知道是8192)
    6. 请求内容的具体处理在adapter.service(request, response);,下篇文章讲解。

    总结

    BIO中,Accepter在接收新的socket连接后,创建新的线程,加入线程池来执行。每个连接(socket)对应一个线程,想必效率有限,也不适合高并发。

    最大支持连接数

    跟踪代码可知,AbstractEndpoint.createExecutor中:

    executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
    

    其中getMaxThreads()最终调用:

     protected int getMaxThreadsExecutor(boolean useExecutor) {
            if (useExecutor && executor != null) {
                if (executor instanceof java.util.concurrent.ThreadPoolExecutor) {
                    return ((java.util.concurrent.ThreadPoolExecutor)executor).getMaximumPoolSize();
                } else if (executor instanceof ResizableExecutor) {
                    return ((ResizableExecutor)executor).getMaxThreads();
                } else {
                    return -1;
                }
            } else {
                return maxThreads;
            }
        }
    

    在executor没创建时,调用return maxThreads;。其中maxThreads在初始化时为200,因此线程池最大只能保持200个线程,支持的连接数应当也小于这个。在executor创建后,调用的是return ((java.util.concurrent.ThreadPoolExecutor)executor).getMaximumPoolSize();,如果没变化(暂时没验证何时会使该值变化)则依旧是200。

    相关文章

      网友评论

          本文标题:tomcat请求分析(2)Socket转换为内部请求

          本文链接:https://www.haomeiwen.com/subject/jofziqtx.html