1.Tomcat 核心架构体系

1.Tomcat 核心架构体系

Tomcat核心组件

组件 职责
Server 服务器表示整个Catalina Servlet容器以及其它组件,负责组装并启动Servlet引擎,Tomcat连接器。Server通过实现Lifecycle接口,提供了一种优雅的启动和关闭整个系统的方式
Service 服务是Server内部的组件,一个Server包含多个Service。它将若干个Connector组件绑定到一个Container(Engine)上
Connector 连接器,处理与客户端的通信,它负责接收客户请求,然后转给相关的容器处理,最后向客户返回响应结果
Container 容器,负责处理用户的servlet请求,并返回对象给web用户的模块
Engine 容器子组件,负责处理连接器发送过来的请求,并分发到指定的Host
Host 容器子组件,虚拟主机,接收处理Engine发送过来的请求,并分发到指定的Context
Context 容器子组件,应用上下文,一个Context对应一个Web Application,接收Host的调用请求,并分发到指定的Wrapper组件
Wrapper 容器子组件,一个Wrapper组件封装了一个Servlet实例

Tomcat执行流程:

启动Tomcat命令startup.bat启动了BootStrap启动类,启动类里有main方法进行初始化加载配置文件。
Tomcat启动后创建Server对象(根实例),Server创建Service(服务组件)接收用户请求和处理用户请求。
Service内分为:
(1)Connector连接器组件:
监听端口、根据协议封装请求数据,创建Request与Response对象交给Container容器组件处理。
连接器可以有多个,默认配置两个连接器,监听8080端口的http协议,监听8009端口的ajp协议,使用apache服务器使用的是ajp协议
(2)Container容器组件:

Connector连接器组件:

Connector连接器的作用:
1.监听端口数据
2.根据协议解析数据
3.封装成Request和Response对象
4.将请求交给容器执行
连接器内部组件:
ProtocolHandler(协议处理器):监听端口,根据协议封装数据
ProtocolHander(协议处理器)支持两种协议:
AJP、Http协议
ProtocolHander(协议处理器)支持的IO模型:
NIO、NIO2、APR(使用C/C++编写的)
ProtocolHandler内部有6个实现类:
AjpNioProtocol
AjpAprProtocol
AjpNio2Protocol
Http11NioProtocol
Http11Nio2Protocol
Http11AprProtocol
支持两种协议处理:Http协议、Ajp协议
共有三种处理方式:Nio、Nio2、Apr
Adapter(适配器):通过映射得到是否存在本次请求对应的资源,存在会将Request、Response对象进一步封装,封装成ServletRequest、ServletResponse对象,调用容器执行,不存在返回404异常。

IO模型与协议

在Connector中 , Tomcat支持的多种I/O模型和应用层协议,具体包含哪些IO模型和应用层协议,请看下表:

Tomcat 支持的IO模型(自8.5/9.0 版本起,Tomcat 移除了 对 BIO 的支持):

IO模型 描述
NIO 非阻塞I/O,采用Java NIO类库实现。 (默认的)
NIO2 异步I/O,采用JDK 7最新的NIO2类库实现。
APR 采用Apache可移植运行库实现,是C/C++编写的本地库。如果选择该方案,需要单独安装APR库。

Tomcat 支持的应用层协议 :

应用层协议 描述
HTTP/1.1 这是大部分Web应用采用的访问协议。
AJP 用于和Web服务器集成(如Apache),以实现对静态资源的优化以及集群部署,当前支持AJP/1.3。
HTTP/2 HTTP 2.0大幅度的提升了Web性能。下一代HTTP协议 , 自8.5以及9.0版本之后支持。

协议分层 :

在 8.0 之前 , Tomcat 默认采用的I/O方式为 BIO , 之后改为 NIO。 无论 NIO、NIO2 还是 APR, 在性能方面均优于以往的BIO。 如果采用APR, 甚至可以达到 Apache HTTP Server 的影响性能。

Tomcat为了实现支持多种I/O模型和应用层协议,一个容器可能对接多个连接器,就好比一个房间有多个门。但是单独的连接器或者容器都不能对外提供服务,需要把它们组装起来才能工作,组装后这个整体叫作Service组件。这里请你注意,Service本身没有做什么重要的事情,只是在连接器和容器外面多包了一层,把它们组装在一起。Tomcat内可能有多个Service,这样的设计也是出于灵活性的考虑。通过在Tomcat中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。

APR > NIO2 > NIO > BIO(8版本前有 并且是默认)

网络IO相关方面的知识点:

Java对BIO、NIO、AIO的支持:
- Java BIO : 同步并阻塞,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
- Java NIO : 同步非阻塞,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
- Java AIO(NIO.2) : 异步非阻塞,即客户端有连接请求时服务器端就需要启动一个线程,但线程不需要主动去获取消息,而是由OS先完成了数据接收,再通知服务器的线程进行处理,
BIO、NIO、AIO适用场景分析:
- BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
- NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
- AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

Container容器组件:

在 Tomcat 里,容器就是用来装载 Servlet 的。

四个组件具有层级关系:Engine、HOST、Context、Wrapper

各个组件的含义 :

容器 描述
Engine 表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最多只能有一个Engine,但是一个引擎可包含多个Host
Host 代表一个虚拟主机,或者说一个站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可包含多个Context
Context 表示一个Web应用程序, 一个Web应用可包含多个Wrapper
Wrapper 表示一个Servlet,Wrapper 作为容器中的最底层,不能包含子容器

一个Tomcat中有一个大的容器Engine引擎,Engine引擎接口继承了Container容器接口 ,Engine引擎内存储多个Host虚拟主机,一个Host虚拟主机内存储多个Context,一个Context内存储多个Wrapper。

一个Context代表一个项目,Wrapper代表一个Servlet容器组件调用我们写的servlet程序,HOST虚拟主机容器

我们也可以再通过Tomcat的server.xml配置文件来加深对Tomcat容器的理解。Tomcat采用了组件化的设计,它的构成组件都是可配置的,其中最外层的是Server,其他组件按照一定的格式要求配置在这个顶层容器中。

那么,Tomcat是怎么管理这些容器的呢?你会发现这些容器具有父子关系,形成一个树形结构,你可能马上就想到了设计模式中的组合模式。没错,Tomcat就是用组合模式来管理这些容器的。具体实现方法是,所有容器组件都实现了Container接口,因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的Wrapper,组合容器对象指的是上面的Context、Host或者Engine。

Tomcat请求的流程(重点)

用户发送请求,被Tomcat服务器内的连接器接收到,监听到端口,根据指定协议进行封装,例如Http协议,封装成Request、Response对象,通过适配器映射得到是否存在本次请求对应的资源,存在会将Request、Response对象进一步封装,封装成ServletRequest、ServletResponse对象,调用容器执行,不存在返回404异常。调用容器中引擎根据路径中的域名找到具体的虚拟主机,虚拟主机根据路径中项目名称找到具体的Context应用程序,应用程序根据路径中资源名找到对应的Servlet,Wrapper组件内封装的就是Servlet,调用我们写的Sevlet方法执行,执行完返回给用户。

http://www.itcast.cn/bbs/findAll
1、用户点击网页内容,请求被发送到本机端口80,被在那里监听的Connector获得。
2. Connector会根据 http协议封装该请求,创建Request 和 Response对象
3. 将Request 和 Response 交给 Adapter适配器处理
4. Adapter适配器查找Mapper缓存 判断资源是否存在.
存在:
封装Request 为 ServletRequest
封装Response 为 ServletResponse
并把请求交给当前所在Service的Engine容器来处理并等待Engine的处理结果
不存在:
报404异常
5、Engine获得请求 http://www.itcast.cn/bbs/findAll,匹配所有的虚拟主机Host。
6、Engine匹配到名为www.itcast.cn的Host(匹配不到把请求交给默认的Host处理),
名为www.itcast.cn的Host获得请求/bbs/findAll,匹配它所拥有的所有的Context。Host匹配到路径为/bbs的Context(如果匹配不到就把该请求交给路径名为"/"的Context去处理)。
7、path=“/bbs”的Context获得请求/findAll,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为 findAll 的Servlet。
8、构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用servlet 的 doGet()或doPost().执行业务逻辑、数据存储等程序。
9、Context把执行完之后的HttpServletResponse对象返回给Host。
10、Host把HttpServletResponse对象返回给Engine。
11、Engine把HttpServletResponse对象返回Connector。
12、Connector把HttpServletResponse对象返回给客户Browser。
posted @   Lz_蚂蚱  阅读(163)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起