Tomcat剖析之架构篇(一)

前言

早在之前写过一些http玩具服务器,总感觉无法继续前进了,期间花了比较多的时间在基础知识上,前段时间想着直接从用的比较多的服务器开始,对于Java开发者来说,自然Tomcat是首选,但有一个比较大的问题是经过了近20年的发展,它已经成为了一个十分系统、复杂的框架了,读起来肯定容易陷入泥潭,回想起之前学其它原理一样,一开始就看了比较复杂的一张架构图,然后就没有然后了…,不过还好有《how tomcat works这种神书,虽说是讲的Tomcat4,5版本的,但关键在于从实际问题出发描述,寻求解决方式,一步步的将其从百来行代码的玩具构建成了一个功能完整的、有着较强扩展性的框架。虽然到现在的Tomcat9版本有较大的变化,但核心还是没变,了解了早期版本的源码之后再看现在的版本就不会像无头苍蝇一样乱撞,从一条线出发,清楚整个流程,学习设计,先不管太多细节性的问题,这也是我看了一些技术书籍和文章之后的体会,发现很多都是只谈概念,不讲这样做的原因,就很难让读者带入自己的思考、融入书本去读,自然难以阅读下去,也容易理解不够深,忘记得也就更加快。用这篇博客主要来解析一下Tomcat的架构,因为Tomcat涉及到的功能模块比较多,这里只从它的核心功能出发,附加的组件只简单介绍一下。本来打算直接写一篇从源码开始的,最后写一个简单的Tomcat的,写的过程中发现很多东西都要去解释,而且难以将前后串起来,所以打算把它拆解成架构篇,源码篇,实践篇一共三篇,基于Tomcat9,这里第一篇主要介绍Tomcat的核心组件,以及整体的架构和运作方式,不会涉及过多的源码,现在开始正文。

Tomcat总体架构

Tomcat本质是一个Web服务器 + Servlet容器, 首先借用一张图看看它的的整体架构
整体架构
可以看到 顶层是一个Server,它是运行着的Tomcat服务器的具体表示,一个Tomcat只能有一个Server,而一个Server可以有多个Service,Service表示完整的服务,用来管理tomcat核心的组件,后面再进行讲述。
所以总的来说,Tomcat需要实现一下两个核心功能,(SpringMVC本质也是对Servlet的封装,将DispatcherServlet加载到tomcat中,将最终请求的处理,使用反射进行相应参数的获取和绑定,然后调用对应的方法,最后还是由tomcat建立的TCP连接通道的包装对象将数据发送出去.)

1. 处理Socket连接, 负责网络字节流与Resquest和Response对象的转换.
2. 加载和管理Servlet,以及请求的具体处理.

因此tomcat设计了两个核心组件连接器(connector) 和 容器(container), 连接器负责对外交流,容器负责内部处理,对应着上述两步。接下来就从连接器开始

连接器

连接器(connector) 内部持有一个实现了ProtocolHandler接口的对象,来看看这个接口具体的实现类的类图
ProtocolHandler

根据名称就可以看出ProtocolHandler其实就是对协议的抽象,先用一个实现了ProtocolHandler接口的抽象类AbstarctProtocol, 然后有两类协议,分别是Ajp和Http1.1协议,这里就用了两个不同的抽象类来分别表示AbstractAjpProtocol和AbstractHttp11Protocol。对于AbstractAjpProtocol类,只有三个子类,刚好分别是使用Nio,Apr,Nio2三种不同IO模型实现的Ajp协议;对于AbstractHttp11Protocol类,也同样是使用了三种不同的IO模型来实现的,不同地方在于对于Nio和Nio2,不是直接是继承了AbstractHttp11Protocol,而是通过一个继承了该类的抽象父类AbstractHttp11JsseProtocol,这实际上就是为了支持传输安全的Socket,也就是我们常见的Https协议(传输的加密与解密实际是在应用层来做的,具体使用了HTTP+ TLS协议来实现)。Http协议应该都比较熟悉了,这里简单介绍一下Ajp协议,众所周知,HTTP协议是基于TCP协议实现的纯文本的一个协议,而Ajp协议是一个基于TCP实现的二进制协议,内部做了较多的优化,我们平时使用的基本都是Http协议,因为浏览器或者操作系统,以及各种网络编程相关的库内部都实现了Http协议,所以我们使用起来都是无感知的。Tomcat内部虽然实现了Ajp协议,但我们的浏览器等基础软件并没有实现,所以肯定是无法直接使用该协议进行数据交互的,因此一个办法就是在服务器端做一个反向代理, 做反向代理的服务器帮我们实现了从Http协议到Ajp的双向转换即可(实际情况实现了Ajp协议的服务器较少,所以Ajp相关的端口默认是关闭的),使用较多的自然就是Apache和Nginx服务器,Apache是直接支持Ajp协议的,而Nginx我看了下官网,没找到相关的,不过看到了第三方实现了Ajp协议的Nginx反向代理的模块(关于Ajp协议的更多信息可以参考Tomcat官方文档https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html)。


ProtocolHandler接口的实现类里面持有一个AbstractEndPoint,这就是真正建立,管理连接的地方,每个EndPoint内部使用了多个Acceptor(每个都是一个新启动的线程)来监听新到来连接请求,建立连接后,会把连接对应的通道注册到一个Poller(轮询器)中,EndPoint里面也是持有了多个Poller(每个也都是一个新启动的线程),当有读写事件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值