Tomcat 架构

一、Http工作原理

        HTTP协议是浏览器与服务器之间的数据传送协议。作为应用层协议,HTTP是基于TCP/IP协议来传递数据的(HTML文件、图片、查询结果等),HTTP协议不涉及数据包(Packet)传输,主要规定了客户端和服务器之间的通信格式。

从图上你可以看到,这个过程是:

1) 用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览器获取了这个事件。

2) 浏览器向服务端发出TCP连接请求。

3) 服务程序接受浏览器的连接请求,并经过TCP三次握手建立连接。

4) 浏览器将请求数据打包成一个HTTP协议格式的数据包。

5) 浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。

6) 服务端程序拿到这个数据包后,同样以HTTP协议格式解包,获取到客户端的意图。

7) 得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。

8) 服务器将响应结果(可能是HTML或者图片等)按照HTTP协议格式打包。

9) 服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。

10) 浏览器拿到数据包后,以HTTP协议的格式解包,然后解析数据,假设这里的数据是HTML。

11) 浏览器将HTML文件展示在页面上。

在这个过程中都做了些什么事情呢?主要是接受连接、解析请求数据、处理请求和发送响应这几个步骤。

二、Tomcat的整体架构

        1.Http服务器请求处理

        浏览器发给服务端的是一个HTTP格式的请求,HTTP服务器收到这个请求后,需要调用服务端程序来处理,所谓的服务端程序就是你写的Java类,一般来说不同的请求需要由不同的Java类来处理。

        图1,表示HTTP服务器直接调用具体业务类,它们是紧耦合的。

        图2,HTTP服务器不直接调用业务类,而是把请求交给容器来处理,容器通过Servlet接口调用业务类。因此Servlet接口和Servlet容器的出现,达到了HTTP服务器与业务类解耦的目的。而Servlet接口和Servlet容器这一整套规范叫作Servlet规范。Tomcat按照Servlet规范的要求实现了Servlet容器,同时它们也具有HTTP服务器的功能。作为Java程序员,如果我们要实现新的业务功能,只需要实现一个Servlet,并把它注册到Tomcat(Servlet容器)中,剩下的事情就由Tomcat帮我们处理了。

        2.Servlet容器工作流程

        为了解耦,HTTP服务器不直接调用Servlet,而是把请求交给Servlet容器来处理,那Servlet容器又是怎么工作的呢?

        当客户请求某个资源时,HTTP服务器会用一个ServletRequest对象把客户的请求信息封装起来,然后调用Servlet容器的service方法,Servlet容器拿到请求后,根据请求的URL和Servlet的映射关系,找到相应的Servlet,如果Servlet还没有被加载,就用反射机制创建这个Servlet,并调用Servlet的init方法来完成初始化,接着调用Servlet的service方法来处理请求,把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端。

        3.Tomcat整体架构

        我们知道如果要设计一个系统,首先是要了解需求,我们已经了解了Tomcat要实现两个核心功能:

        处理Socket连接,负责网络字节流与Request和Response对象的转化。

        加载和管理Servlet,以及具体处理Request请求。

        因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流,容器负责内部处理。

三、连接器 - Coyote

        1.架构介绍

        Coyote 是Tomcat的连接器框架的名称, 是Tomcat服务器提供的供客户端访问的外部接口。客户端通过Coyote与服务器建立连接、发送请求并接受响应 。

        Coyote 封装了底层的网络通信(Socket 请求及响应处理),为Catalina 容器提供了统一的接口,使Catalina 容器与具体的请求协议及IO操作方式完全解耦。Coyote 将Socket输入转换封装为Request对象,交由Catalina 容器进行处理,处理请求完成后, Catalina 通过Coyote 提供的Response 对象将结果写入输出流 。

        Coyote 作为独立的模块,只负责具体协议和IO的相关操作,与Servlet规范实现没有直接关系,因此即便是Request和Response对象也并未实现Servlet规范对应的接口, 而是在Catalina 中将他们进一步封装为ServletRequest 和 ServletResponse 。

        2.I/O模型与协议

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

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

        Tomcat支持的应用层协议:

        协议分层:

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

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

        3.连接器组件

        连接器中的各个组件的作用如下:

        EndPoint

        1) EndPoint : Coyote 通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的。

        2) Tomcat 并没有EndPoint 接口,而是提供了一个抽象类AbstractEndpoint,里面定义了两个内部类:Acceptor和SocketProcessor。Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到线程池来执行。而这个线程池叫作执行器(Executor)。

        Processor

        Processor : Coyote 协议处理接口 ,如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。

        ProtocolHandler

        ProtocolHandler: Coyote协议接口,通过Endpoint和Processor,实现针对具体协议的处理能力。

        Tomcat 按照协议和I/O 提供了6个实现类 : AjpNioProtocol、AjpAprProtocol、AjpNio2Protocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol。

        我们在配置tomcat/conf/server.xml时,至少要指定具体的ProtocolHandler,当然也可以指定协议名称,如:HTTP/1.1 ,如果安装了APR,那么将使用Http11AprProtocol,否则使用 Http11NioProtocol。

        Adapter

        由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,也就意味着,不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是TomcatRequest对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。

四、容器 - Catalina

        Tomcat是一个由一系列可配置的组件构成的Web容器,而Catalina是Tomcat的servlet容器。

        Catalina 是Servlet 容器实现,包含了之前讲到的所有的容器组件,以及后续章节涉及到的安全、会话、集群、管理等Servlet 容器架构的各个方面。它通过松耦合的方式集成Coyote,以完成按照请求协议进行数据读写。同时,它还包括我们的启动入口、Shell程序等。

        1.Catalina 地位

        Tomcat的模块分层结构图,如下:

        Tomcat 本质上就是一款 Servlet 容器,因此Catalina 才是Tomcat 的核心,其他模块都是为Catalina 提供支撑的。比如 :通过Coyote 模块提供链接通信,Jasper 模块提供JSP引擎,Naming 提供JNDI 服务,Juli 提供日志服务。

        2.Catalina 结构

        Catalina 的主要组件结构如下:

        如上图所示,Catalina负责管理Server,而Server表示着整个服务器。Server下面有多个服务Service,每个服务都包含着多个连接器组件Connector(Coyote 实现)和一个容器组件Container。在Tomcat 启动的时候, 会初始化一个Catalina的实例。

        Catalina 各个组件的职责:

        3.Container 结构

        Tomcat设计了4种容器,分别是Engine、Host、Context和Wrapper。这4种容器不是平行关系,而是父子关系。, Tomcat通过一种分层的架构,使得Servlet容器具有很好的灵活性。

        各个组件的含义 :

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

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

        Container 接口中提供了以下方法(截图中知识一部分方法):

        在上面的接口看到了getParent、SetParent、addChild和removeChild等方法。

        Container接口扩展了LifeCycle接口,LifeCycle接口用来统一管理各组件的生命周期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/267041.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汇编反外挂

在软件保护领域,尤其是游戏保护中,反外挂是一个重要的议题。外挂通常指的是一种第三方软件,它可以修改游戏数据、操作游戏内存或提供其他作弊功能,从而给玩家带来不公平的优势。为了打击外挂,游戏开发者会采取一系列措…

PyQt6的开发流程(密码生成小程序为例)

PyQt6的开发流程(密码生成小程序为例) 文章目录 PyQt6的开发流程(密码生成小程序为例)一、流程介绍与概览1. 界面与逻辑分离的开发流程2. PyQt6的开发流程 二、打开 designer.exe 创建文件三、用QT设计师绘制界面保存成ui1. QT常用…

Python实现MACD工具判断信号:股票技术分析的工具系列(1)

Python实现MACD工具判断信号:股票技术分析的工具系列(1) 介绍代码rolling函数介绍核心代码计算指数移动平均值计算MACD指标 完整代码 介绍 先看看官方介绍: MACD (平滑异同平均线) 指标说明 DIF线:收盘价短…

“智农”-数字乡村可视化

“智农”打造数字乡村可视化,结合乡村区域实际情况,以规划完善乡村机制体系和更好服务乡村振兴为目标,坚持可持续、可复制、可扩展的建设原则,着力解决农村信息孤岛,提高农村种植技术,加快农村信息化和产业…

前端按钮动画

效果示例 代码示例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevic…

echarts vue 动画效果的水球图、波浪图教程

1、安装插件 前提是已经安装了echarts&#xff08;我的版本是4.2.1&#xff09; npm install echarts-liquidfill --save 我安装了3.1.0版本的&#xff0c;结果运行时报错"TypeError: wave.ensureState is not a function" 原因&#xff1a;echarts版本和echarts-l…

IDC 中搭建 Serverless 应用平台:通过 ACK One 和 Knative 玩转云资源

作者&#xff1a;元毅、庄宇 如何打造云上&#xff08;公共云&#xff09;、云下&#xff08;IDC 数据中心&#xff09;统一的云原生 Serverless 应用平台&#xff0c;首先我们来看一下 ChatGPT 4 会给出什么样的答案&#xff1a; 如何打造云上、云下统一的云原生 Serverless…

MySQL 多表查询 连接查询 内连接

介绍 内连接查询是两张表中交集的部分 连接模式 隐式内连接 SELECT 字段列表 FROM 表1,表2 WHERE 条件显式内连接 SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件案例 有两张表一个表为学生表&#xff0c;另一个表为班级表&#xff0c;现在需要查询学生时候在查…

2023中国PostgreSQL数据库生态大会:洞察前沿趋势,探索无限可能(附核心PPT资料下载)

随着数字化浪潮的推进&#xff0c;数据库技术已成为支撑各行各业数字化转型的核心力量。2023中国PostgreSQL数据库生态大会的召开&#xff0c;无疑为业界提供了一个深入交流、共同探索PostgreSQL数据库技术未来发展趋势的平台。本文将带您走进这场盛会&#xff0c;解析大会的亮…

Laravel Octane 和 Swoole 协程的使用分析二

又仔细研究了下 Octane 源码和 Swoole 的文档&#xff0c;关于前几天 Laravel Octane 和 Swoole 协程的使用分析中的猜想&#xff0c;得到进一步验证&#xff1a; Swoole 的 HTTP Server 启动后会创建一个 master 进程和一个 manager 进程&#xff1b;master 进程又会创建多个…

XUbuntu22.04之解决:仓库xxx没有数字签名问题(二百一十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Linux 系统安装/卸载 Nginx教程

优质博文&#xff1a;IT-BLOG-CN 一、安装Nginx 【1】首先通过Nginx官网确定需要安装的版本&#xff0c;如果Linux联网则直接在Linux服务上使用wget命令将Nginx安装包下载到/usr/local/目录下&#xff1a; [rootxxx local]# wget -c http://nginx.org/download/nginx-1.22.1.…

qt 5.15版本安装

1.qt5.15版本安装 2.安装慢时&#xff0c;切换到清华镜像源&#xff1a;.\qt-unified-windows-x64-online.exe --mirror https://mirrors.tuna.tsinghua.edu.cn/qt/ 3.没有qt 5.15版本在旁边进行筛选&#xff0c;只选archive

雅马哈伺服器TS-S系列说明具体详情内容可参看PDF目录内容

雅马哈伺服器TS-S系列说明具体详情内容可参看PDF目录内容

c++结构体内存对齐

结构体内存对齐 试试运行下面的例子 #include <stdio.h> #include <stdlib.h>using namespace std;struct A{char c;int i; };struct B{char c; int i; double d; };struct C{char c;int i;double d;char c1; };int main(){printf("sizeof(A): %d\n"…

netlink原理及应用

什么是netlink netlink是一种基于网络的通信机制&#xff0c;允许内核内部、内核与用户态应用之间甚至用户态应用之间进行通信&#xff1b;netlink的主要作用是内核与用户态之间通信&#xff1b;它的思想是&#xff0c;基于BSD的socket使用网络框架在内核和用户态之间进行通信…

CloudCanal x Hive 构建高效的实时数仓

简述 CloudCanal 最近对于全周期数据流动进行了初步探索&#xff0c;打通了Hive 目标端的实时同步&#xff0c;为实时数仓的构建提供了支持&#xff0c;这篇文章简要做下分享。 基于临时表的增量合并方式基于 HDFS 文件写入方式临时表统一 Schema任务级的临时表 基于临时表的…

0基础跨考计算机|408保姆级全年计划

我也是零基础备考408&#xff01; 虽说是计算机专业&#xff0c;但是本科一学期学十几门,真的期末考试完脑子里什么都不进的...基本都是考前一周发疯学完水过考试...&#x1f605; 想要零基础跨考可以直接从王道开始&#xff01;跟教材一点一点啃完全没必要&#x1f978; 现在…

ThreadLocal 为什么会内存泄漏吗?是怎么产生的?

ThreadLocal是什么 ThreadLocalMap 如何避免泄漏 ThreadLocal是什么 ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射&#xff0c;各个线程之间的变量互不干扰&#xff0c;在高并发场景下&#xff0c;可以实现无状态的调用&…

vscode 引入外部依赖包

背景 我要在vscode中写一些antlr代码生成的cpp代码&#xff0c;但是在引入头文件#include "antlr4-runtime.h"的时候&#xff0c;出现报错&#xff0c;显示没有这个头文件&#xff0c;显然这是我们没有导入相关的包&#xff0c;因此我首先尝试了将antlr4的依赖源码在…