专栏首页java 成神之路Tomcat connector 实现原理

Tomcat connector 实现原理

Bootstrap.main()->Bootstrap.init()

BootStrap.init()

bootstrap.init() 方法中设置catalinaDaemon

创建 Connector 对象

Bootstrap.main()->Bootstrap.start()->Catalina.start()->Catalina.load()->Catalina.createStartDigester()

createStartDigester() 方法

  1. 创建connector对象,并判断server.xml 中是否配置线程池,如果配置线程池则创建线程池

server.xml 配置

  1. 为connector对象设置除executor外的其它属性信息
  2. 把当前connector添加到StandardService.connectors 数组中。

Connector

构造

通过protocol协议来判断使用那个protocolHandler。

setProtocol 方法

tomcat 默认配置 是以BIO的模式启动的,默认会调用org.apache.coyote.http11.Http11Protocol。 下面我们以Http11Protocol来分析Connector。

startInternal() 方法

startInternal() 方法

  1. 设置tomcat状态为,正在启动
  2. 启动 connector。

Http11Protocol

Http11Protocol 构造方法

  1. 在构造方法中创建JIoEndpoint和Http11ConnectionHandler对象
  2. 设置 socket 参数

AbstractEndpoint.start() 方法

public class JIoEndpoint extends AbstractEndpoint

JIoEndpoint 继承 AbstractEndpoint

start()

JIoEndpoint .bind() 方法

在这创建connector的socket服务,使用serverSocket监听入站连接。

JIoEndpoint.startInternal() 方法

  1. 判断线程池是否为空,如果为空则创建默认的线程池。(server.xml的connector中配置的线程池)
  2. 根据server.xml中的connector中的acceptorThreadCount属性来确定创建几个接受请求处理的线程。 Acceptor类,负责处理接受客户端请求的处理。

server.xml 中配置如下: <Connector port="8080" protocol="HTTP/1.1" acceptorThreadCount="2" redirectPort="8443"/>

acceptorThreadCount 个数建议和CPU的个数一致。

createExecutor() 方法

createExecutor() 方法

默认创建的线程池,最小线程数为10,最大线程数为200,空闲时间为60秒,队列为LinkedBlockingQueue,队列大小默认为Ineteger.MAX_VALUE。

这里需要注意的是,如果队列中的元素没有存满,那么线程的数量一直会是10,而不会自动扩大到200。所以建议大家自己设置一个线程池,而不要用默认的

Acceptor 类

Acceptor.run() 方法
  1. 获取之前创建的serverSocket。 2.设置socket的参数
  2. 调用processSocket 处理请求的socket

processSocket() 方法

把socket封装成SocketWrapper对象 传给SocketProcessor对象,并提交给线程池处理。

SocketProcessor

负责解析http协议信息。 SOcketProcessor重要属性

Paste_Image.png

inputBuffer:包装socket的inputStream,并解析http协议信息。 outputBuffer:包装socket的outputStream,负责响应用户的数据。

run() 方法

run() 方法

在process方法中处理解析http协议信息。

Http11Processor.process() 方法

Http11Protocol.process()->Http11Processor.process() 代码如下:

Http11Processor.process()

获取socket的输入流和输出流

Http11Processor构造方法

在这里,构造Request和Response对象。

解析http协议

解析完后的数据存储到 AbstractInputBuffer的下面两个属性中

    protected Request request;
    protected MimeHeaders headers;

request对象就是 HttpServletRequest 对象的原型。

解析完之后,调用下面的service方法。

这里的service方法会调用servlet中的service方法并传入request和response对象,然后根据请求的方法来决定调用的是servlet的doGet方法还是doPost或其它的方法。

到此 Connector的整理流程就结束了。

简单梳理下

1. Connector

根据协议来选择协议的处理类,tomcat默认的处理类是Http11Protocol。

2. JIoEndpoint

  1. 创建ServerSocket 连接
  2. 创建接受请求的线程 Acceptor对象。
  3. 创建处理请求的线程池 executor。

3. Http11Processor

主要负责解析http协议的

  1. 解析请求行 (来确定http协议、请求的url、请求的method)
  2. 解析请求头 headers 3.并把解析后的结果交给 Container 处理

connector 可配置的部分参数

参数值根据自己项目做响应修改。下面的只是个例子

<Connector port="8080" protocol="HTTP/1.1"
    acceptCount="1000"
    disableUploadTimeout="true"
    enableLookups="false"
    keepAliveTimeout="20"
    maxThreads="500" 
    minThreads="500"
    maxProcessor="500"
    minSpareThreads="20"
    maxKeepAliveRequests="1"
    connectionTimeout="20" 
    redirectPort="8443"
    allowTrace="false"
    acceptorThreadCount="2"
    acceptorThreadPriority="7"
    socket.tcpNoDelay="true"
    threadPriority="8"
    tcpNoDelay="true"
    compression="on"
    emptySessionPath="true"
/>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java 线程池

    java404
  • 并发编程基础知识点

    java404
  • Spring bean 标签加载、解析过程分析

    java404
  • Java面试题系列之基础部分(七)——每天学5个问题

    Java基础部分学习的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io的语法,虚拟机方面的语法,这些都是最基...

    用户1289394
  • 创建线程到底有多少种方式?

    话不多说,金九银十,很多同学马上就要参加秋招了。而多线程肯定是面试必问的,开篇之前,问大家一个问题:创建线程到底有几种方式?

    一个优秀的废人
  • Java多线程系列(二)-----实现方式

    版权声明:欢迎转载,请标明出处,如有问题,欢迎指正!谢谢!微信:w1186355422 ht...

    IT云清
  • 多线程的实现方法

          从Thread类中实例化的对象即代表线程,启动一个线程就是建立一个Thread实例。因为完成线程真正功能的代码放在类的run()方法中,所以可以将线...

    sr
  • Tomcat优化(内存,并发,缓存,安全,网络,系统等)

    3.配置示例: JAVA_OPTS=’-Xms1024m -Xmx2048m -XX: PermSize=256M -XX:MaxNewSize=256m -...

    菲宇
  • 使用 Synchronized 关键字

    使用 Synchronized 关键字来解决并发问题是最简单的一种方式,我们只需要使用它修饰需要被并发处理的代码块、方法或字段属性,虚拟机自动为它加锁和释放锁,...

    Single
  • Java并发编程实战

    在我们的实际应用当中可能经常会遇到这样一个场景:多个线程读或者、写相同的数据,访问相同的文件等等。对于这种情况如果我们不加以控制,是非常容易导致错误的。在jav...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券