IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 聊一聊Tomcat 系统架构设计 -> 正文阅读

[Java知识库]聊一聊Tomcat 系统架构设计

总体架构

Tomcat 是一个应用服务器,那么要开发一个应用服务器,首先捋一捋它的需求,要实现那些功能。

1、 首先可以和客户端建立连接,并且能够处理客户端的连接

2、 其次还要解析处理我们写的 Servlet

3、 最后能够根据客户端的请求找到相应的 Servlet。

在 Tomcat 中将这些需求分为了两大功能

  • 处理 Socket 连接,并将网络字节流转换成 Request 对象和 Response 对象
  • 解析、加载和管理 Servlet,处理请求并返回响应数据

Tomcat 将这两大功能,设计成了两个主要的组件

  • 连接器(Connector)
  • 容器(Container)

来看一下 Tomcat 的总体架构

all

上图中是 tomcat 的整体架构,一个 Tomcat 代表一个 Server,一个 Server 下包含对个 Service,每个 Service 下包含多个连接器和一个容器。

Service 本身没有什么重要的作用,它只是把连接器和容器组装在一起了,但是 Tomcat 可以同时设置多个 Service,也就可以部署多个服务。比如有两个相同的项目,可以把这两个项目放到两个 Service 里,那这两个相同的项目就可以在一个 Tomcat 里运行了,不用担心冲突的问题。

这些配置可以在 conf/server.xml 中查看。

接下来重点关注一下连接器和容器,这是 Tomcat 工作的核心。

连接器(Connector)

在分析连接器之前,先了解一下 Tomcat 支持的 I/O 模型和应用层协议。

I/O 模型:

  • NIO:非阻塞 I/O, Java NIO 类库实现。
  • NIO2:异步 I/O, JDK 7 最新的 NIO2 类库实现。
  • APR: Apache 可移植运行库实现,是 C/C++ 编写的本地库。

应用层协议:

  • HTTP/1.1
  • AJP:用于和 Web 服务器集成(如 Apache)。
  • HTTP/2:HTTP 2.0 大幅度的提升了 Web 性能。

Service 中存在多个连接器就是为了支持 Tomcat 的多个 I/O 模型和应用层协议。

OK,现在来分析连接器。

首先可以先看一看 Tomcat 中连接器的配置

    <Connector port="24100" protocol="HTTP/1.1"
               connectionTimeout="20000"
               compression="on"
               compressionMinSize="2048"
               noCompressionUserAgents="gozilla, traviata"
               compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/jpeg,image/gif" />

连接器中配置了监听的端口和使用的应用层协议等信息。

在上面说了,连接器的主要作用是处理 Socket 连接,并将网络字节流转换成 Request 对象和 Response 对象。那么我可以再试着捋一捋连接器的需求

1、 监听端口

2、 建立连接

3、 获取客户端传输的字节流

4、 根据应用层协议解析字节流,将解析的数据交给容器处理

5、 容器返回响应

6、 将响应转换成字节流返回给客户端

根据以上的需求,Tomcat 将整个连接器分为了三部分

  • 网络通信
  • 解析应用层协议
  • 与容器进行交互

Tomcat 将这三个功能分成了三个模块:Endpoint、Processor 和 Adapter,三个模块只通过抽象接口进行交互,封装了变化,降低了耦合度。

三个模块的处理逻辑为:

1、Endpoint 接收字节流,并交给 Processor。

2、Processor 拿到字节流后,将字节流解析成 Tomcat Request 对象并交给 Adapter。

3、Adapter 拿到 Tomcat Request 对象再解析成 ServletRequest 交给容器。

Tomcat 并没有直接将字节流解析成 ServletRequest 而是先解析成了 Tomcat Request,再通过 Adapter 进行转换,这样做的好处可以使连接器和容器接偶,我们可以自己实现 Adapter 的功能,来对接我们自己实现的类似容器的功能。

由于 Tocmat 支持多种 I/O 模型和应用层协议,并且这些 I/O 模型和应用层协议可以自由组合,比如 NIO + HTTP 或者 NIO2 + AJP。Tomcat 设计了一个 ProtocolHandler,将网络通信和解析应用层协议放到了一起,来封装这两点的变化。

来看一下连接器的结构图

connter

来看一下连接器各个组件的代码结构

Endpoint

Endpoint 不是一个接口,只有对应的实现类 AbstractEndpoint

Endpoint

AbstractEndpoint 的实现类中包含了 Tomcat 支持的 I/O 模型。

Processor

Processor

Processor 的实现类是包含了 Tomcat 支持的所有应用协议。

ProtocolHandler

ProtocolHandler

ProtocolHandler 的实现类里包含了每一种 I/O 模型和协议的组合。

Adapter

Adapter 只有一个实现类 CoyoteAdapter,CoyoteAdapter 是一个典型的适配器模式的使用,ProtocolHandler 中将不同的 IO 模式和不同的应用层协议通过 Endpoint 和 Processor 封装成 Tomcat Request,这个 Request 在 Adapter 中转换成标准的 ServletRequest。这其实也是一个扩展点,我们可以实现自己的 Adapter,拿到 Request 进行自己的业务处理,甚至可以不用 Servlet 那一套,自己定义一套新的应用处理模式。

容器(Container)

容器的作用是解析、加载和管理 Servlet,处理请求并返回响应数据。在 Tomcat 中设计了四种容器 Engine、Host、Context 和 Wrapper,这四种容器是父子关系。

  • Engine 表示引擎,用来管理多个虚拟站点

  • Host 代表的是一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址

  • Context 表示一个 Web 应用程序,也是就我们写的一个项目

  • Wrapper 表示一个 Servlet

一个 Service 最多只能有一个 Engine,一个 Engine 中可以包含多个 Host,一个 Host 中可以包含多个个 Context,一个 Context 可以包含多个 Wrapper

看一下它的结构图

Container

可以结合 conf/server.xml 配置文件来理解容器的设计

<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">

    <!--连接器-->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <!--容器-->
    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
      </Host>
    </Engine>
  </Service>
</Server>

Tomcat 容器是怎么确定请求的是那个 Servlet 的呢?

通过一个例子来说明一下,图片是盗来的,哈哈哈哈。

demo

上面这个例子中,要访问 http://user.shopping.com:8080/order/buy。Tomcat通过连接器解析数据后,交给容器,

1、 根据域名找到对应的 Host,也就是在 conf/server.xml 中配置的和 Host 的 name 相同的 Host

2、根据 URL 找到 Context

3、根据 URL 找到 Wrapper(Servlet)

当连接器将数据给到容器后,并不是直到找到 Servlet 才开始处理数据,容器的每一层都会对数据进行一些处理。Tomcat 用了一个叫做 Pipeline-Valve 管道的方式来对数据进行处理。

Pipeline-Valve 管道

Pipeline-Valve 管道是一种责任链模式,其中 Valve 表示一个处理点,Pipeline 中包含多个 Valve,每个容器中包含一个 Pipeline,每个容器中的 Pipeline 必须包含一个 BasicValve,处于调用的最末端,负责调用下个容器的 Value。

用一张图来解释一下

Pipeline-Valve

Wrapper 容器的最后一个 Valve 会创建一个 Filter 链,并调用 doFilter 方法,最终会调到 Servlet 的 service 方法。

来看一下容器的代码结构

Tomcat 设计了一个顶层的容器接口

public interface Container extends Lifecycle {

     public Container getParent();

     public void setParent(Container container);

     public void addChild(Container child);

   // ....省略
}

各个容器继承了这个顶层的容器

ContainerClass

Container中定义了操作父容器和子容器的方法,很明显的组合模式。

再来看看每个实现类的结构

standContainerClass

每个类同时又继承了一个 Container 的实现抽象类ContainerBase,看一下这个类

public abstract class ContainerBase extends LifecycleMBeanBase
        implements Container {

    protected final Pipeline pipeline = new StandardPipeline(this);

    // ....省略
}

在 ContainerBase 中有Pipeline的属性,这就是 Pipeline-Valve 管道。

OK,最后结合Java类来看看Tomcat组件的总体结构。

class

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:37:37  更:2021-12-23 15:38:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:26:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码