tomcat的原理-组件connector

tomcat 发展多年,成熟而稳定, 但是在当今最新求快的 java web 技术栈中,这种优秀的中间件却与我们渐行渐远。
静下心来学习 , 赏析大牛们是如何设计和架构一个优秀的中间件系统,如有错误,共同探讨,共同学习。

宏观架构

tomcat 的启动流程: startup.sh -> catalina.sh start ->java -jar org.apache.catalina.startup.Bootstrap.main()

先上小图,一图以避之,看个大概。


image.png

所有组件:
1.server: 一个tomcat实例
2.service: 处理即将到来的socket服务
3.connector : socket 连接器 , http协议的转化
4.container : 加载管理servlet 并处理request
其中核心组件 为connector, container

预备知识 :

  1. tomcat组件实现了lifeCyle接口 生命周期方法为: init-> start -> stop-> destroy
  2. tomcat组件继承了lifeCyleBase 抽象类
  3. lifeCyleBase 抽象类 中实现了 lifeCycle接口的方法, 并且个主键在调用相应的生命周期方法会调用内部的 initInternal startInternal stopInternal destroyInternal 方法
    关于组件的初始化 启动 停止 销毁 我们后续探讨。

connector

  1. 构造函数初始化


    image.png

connector 是通过此构造器创建的【上层如何创建这个对象 ,我们后续再说

看一下 ProtocolHandler 的创建过程


image.png
image.png
image.png
image.png

到这里已明白, protocolHandler 默认使用Http11NioProtocol .
Http11NioProtocol 对象创建时候 属性 endpoint 被赋值为 NioEndpoint 对象。
Http11NioProtocol handler 属性设置为 ConnectionHandler
Endpoint handler 属性设置为 ConnectionHandler

  1. 初始化init

a> 创建 CoyoteAdapter 并注册到protocolHandler 中


image.png

b> protocolHandler 【即 构造函数初始化 分析的Http11NioProtocol 】初始化, 先看下ProtocolHandler 的体系图。


image.png

image.png

初始化过程:
Http11NioProtocol.init()->AbstractHttp11Protocol.init()->AbstractProtocol.init()
即子类初始化调用父类初始化。

在 AbstractProtocol.init() 中 endpoint 初始化:

image.png

c.endpoint初始化
看下endpint 的类继承关系


image.png

类: NioEndpoint 方法 init()

image.png

类: AbstractEndpoint 方法: init()


image.png

类: NioEndpoint 方法 : bind()


image.png

类: NioEndpNioEnoint 方法 : initServerSocket()


image.png

3.启动start() 方法
类 : Connector 方法 : startInternal()


image.png

类 : AbstractProtocol 方法: start()


image.png

类: NioEndpNioEnoint 方法 : startInternal()


image.png

我们分析下红色箭头 3,4 中的创建 poller 线程 和 acceptor 线程的作用是什么?

先看Accetpor 线程:
1.实现了runnable 接口 ,在run()方法中:

image.png

image.png

再看poller 线程:


image.png

Abs


image.png
image.png

至此,Acceptor跑在一个单独的线程里,它在一个死循环里调用 accept方法来接收新连接,一旦有新的连接请求到来,accept方法返回一个 Channel 对象,接着把 Channel对象交给 Poller 去处理。
Poller 的本质是一个 Selector,也跑在单独线程里。Poller在内部维护一个 Channel数组,它在一个死循环里不断检测 Channel的数据就绪状态,一旦有 Channel可读,就生成一个 SocketProcessor任务对象扔给 Executor去处理。
我们来看下processSocket方法是如何处理socketWrapper的?

类: AbstractEndpoint 方法 : processSocket


image.png

看下SocketProcessor类的作用

类: NioEndpoint.SocketProcessor
创建:


image.png

看下继承关系:

image.png

当使用线程池执行的时候,活执行父类SocketProcessorBase 的run()方法 ,父类的run()方法 会调用子类SocketProcessor的doRun()方法。

类: NioEndpoint.SocketProcessor 方法 : doRun()


image.png

我们知道在创建Http11NioProtocol 对象的同时 ,创建了NioEndpoint ,并给NioEndpoint 设置handler 属性为 ConnectionHandler , 我们看下
ConnectionHandler 的 process 方法。

image.png
image.png

会调用Http11NioProtocol 的 createProcessor方法 创建 Http11Processor 对象 http11Processor继承关系如下 :


image.png

AbstractProcessorLight类中 的process() 方法


image.png

子类: Http11Processor 的service()方法


image.png

我们知道在 Connector组件初始化的时候 给protocolHandler设置了adapter属性,如下:


image.png

也就是说: getAdapter().servcive(req , rep) 交给了CoyoteAdapter 适配器来处理。

image.png

自此, connector 组件如何处理一个socket 请求,分析完毕

总结:

1.一个connector组件 可分为 protocolHandler 和 Adapter ,protocolHandler 用于处理 网络请求 , Adapter 将内部request , response 适配成 servlet的HttpServletReqeust , HttpServiceResponse

  1. protocolHandler主要处理 网络连接 和 应用层协议 ,包含了两个重要部件 EndPoint 和 Processor, EndPoint 是用来实现 TCP/IP 协议数据读写的,本质调用操作系统的 socket 接口 , Processor用于处理socket, 转换应用层协议 ,封装内部 request 和 response

  2. adapter 用于 内部 request 和 response 转换 成sevlet 规范的 HttpServletReqeust , HttpServiceResponse

  3. EndPoint 一图以避之


    image.png
  4. Processor 用来实现 HTTP 协议,Processor 接收来自 EndPoint 的 Socket,读取字节流解析成 Tomcat Request 和 Response 对象,并通过 Adapter 将其提交到容器处理,Processor 是对应用层协议的抽象


    image.png

最后简图总结下:

protocl.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容