Tomcat connector 实现原理

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


bootstrap.init() 方法中设置catalinaDaemon

创建 Connector 对象

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

createStartDigester() 方法


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

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

Connector

构造


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

setProtocol 方法


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

startInternal() 方法


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

Http11Protocol

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

AbstractEndpoint.start() 方法

public class JIoEndpoint extends AbstractEndpoint

JIoEndpoint 继承 AbstractEndpoint

JIoEndpoint .bind() 方法


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

JIoEndpoint.startInternal() 方法


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

server.xml 中配置如下:

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

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重要属性

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

run() 方法


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

Http11Processor.process() 方法

Http11Protocol.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"
/>

本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8    
点击这里快速进入简书

GIT地址:http://git.oschina.net/brucekankan/
点击这里快速进入GIT

你可能感兴趣的:(tomcat,tomcat,连接器,接受请求,connector)