Tomcat总体架构(一)

目录

一、Server

二、Connector 和 Container(实际为Engine)

三、Context

四、Host

五、Wrapper

六、Container(真正的Container)

七、Lifecycle

视频

Tomcat总体架构(二)

一、Server

从最基本的功能来讲,我们可以将服务器描述为这样一个应用 它接收其他计算机(客户端)发来的请求数据并进行解析, 完成相关业务处理,然 后把处理结果作为响应返回给请求计算机(客户端)。 通常情况下,我们通过使用Socket监听服务器指定端口来实现该功能。按照该描述,一个最简单地服务器设计如图2-1所示。

Tomcat总体架构(一)

二、Connector 和 Container(实际为Engine)

很快我们就会发现,将请求监听与请求处理放到一起扩展性很差,比如当我们想适配多种网络协议,但是请求处理却相同的时候。 自从Tomcat诞生起,它就始终支持与Apache集成,无论是通过AJP协议还是通过HTTP协议。 当Web应用通过Tomcat独立部署时,我们选择使用HTTP协议为客户端提供服务; 当通过Apache进行集群部署时,我们使用AJP协议与Wed服务器(Apache )进行链接。应用服务器(Tomcat)在两种部署架构下切换时,应确保Web应用不需做任何变更。 那么我们如何通过面向对象的方式来解决这个问题?自然的想法就是将网络协议与请求处理从概念上分离。 于是,我们做了如下改进(见图2-2 )。

Tomcat总体架构(一)

一个Server可以包含多个Connector和Container。其中:
Connector负责开启Socket并监听客户端请求、返回响应数据; Container负责具体的请求处理。 Connector和Container分别拥有自己的start()和stop()方法来加载和释放自己维护的资源。

但是,这个设计有个明显的缺陷。既然Server可以包含多个Connector和Container,那么如何知晓来自某个Connector的请求由哪个Container处理呢?

当然,我们可以维护一个复杂的映射规则来解决这个问题,但是这并不是必需的,后续章节你会发现Container的设计已经足够灵活,并不需要一个Connector链接到多个Container。更合理的方式如图2-3所示。

Tomcat总体架构(一)

一个Server包含多个Service(它们互相独立,只是共享一个JVM以及系统类库), 一个Service负责维护多个Connector和一个Container,这样来自Connector的请求只能由它所属Service维护的Container处理。

在Tomcat中,Container是一个更加通用的概念。为了与Tomcat中的组件命名一致,我们将 Container重新命名为Engine,用以表示整个Servlet引擎。修改后的设计如图2-4所示。

需要注意此处的描述,Engine表示整个Servlet引擎,而非Servlet容器。表示整个Servlet容 器的是Server。引擎只负责请求的处理,并不需要考虑请求链接、协议等的处理。

Tomcat总体架构(一)

三、Context

上面的设计已经解决了网络协议和容器的解耦,但是应用服务器是用来部署并运行Web应用的,是一个运行环境,而不是一个独立的业务处理系统。 因此,我们需要在Engine容器中支持管理Web应用,当接收到Connector的处理请求时,Engine容器能够找到一个合适的Web应用来处理。

那么在图2-4的设计方案的基础上,一种比较朴素的实现方案如图2-5所示。

Tomcat总体架构(一)

我们使用Context来表示一个Web应用,并且一个Engine可以包含多个Contex

Context也拥有start()和stop()方法,用以在启动时加载资源以及在停止时释放资源。采 用这种方式设计,我们将加载和卸载资源的过程分解到每个组件当中,使组件充分解耦,提高服务器的可扩展性和可维护性。在后续讲解过程中,新增组件多数也会有相同方法,我们不再赘述。

四、Host

这是不是个合理的方案呢?*

设想我们有一台主机,它承担了多个域名的服务,如news.myCompany.com和 article.myCompany.com均由该主机处理,我们应如何实现呢?

当然,我们可以在该主机上运行多个服务器实例,但是如果我们希望运行一个服务器实例呢?

因为,作为应用服务器,我们应提供尽量灵活的部署方式。 既然我们要提供多个域名的服务,那么就可以将每个域名视为一个虚拟的主机,在每个虚拟主机下包含多个Web应用。因为对于客户端用户,他们并不了解服务端使用几台主机来为他们提供服务,只知道每个域名提供了哪些服务,因此,应用服务器将每个域名抽象为一个虚拟主机从概念上是合理的.

根据这个想法修改后的设计如图2-6所示。

Tomcat总体架构(一)

我们用Host表示虚拟主机的概念,一个Host可以包含多个Context。

在Tomcat的设计中,Engine既可以包含Host,又可以包含Context,这是由具体的Engine实现确定的,而且Tomcat采用一种通用的概念解决此问题,我们在后续部分会详细讲解。Tomcat提供的默认实现StandardEngine只能包含Host。

五、Wrapper

如果阅读Servlet规范,我们就会知道,在一个Web应用中,可包含多个Servlet实例以处理来自不同链接的请求。因此,我们还需要一个组件概念来表示Servlet定义。 在Tomcat中,Servlet定义被称为Wrapper,基于此修改后的设计如图2-7所示.

Tomcat总体架构(一)

六、Container(真正的Container)

截至目前,我们多次提到”容器”这个概念。尽管在具体的小节中,容器的含义并不相同,有时候指Engine,有时候指Context,但是它却代表了一类组件,这类组件的作用就是处理接收自客户端的请求并且返回响应数据。尽管具体操作可能会委派到子组件完成,但是从行为定义上,它们是一致的。 基于这个概念,我们再次修正了我们的设计,如图2-8所示。

我们使用Container来表示容器, Container可以添加并维护子容器,因此Engine 、 Host , Context,Wrapper均继承自Container。我们将它们之间的组合关系改为虚线,以表示它们之间是弱依赖的关系,即它们之间的关系是通过Container的父子容器的概念体现的。不过Service持有的是Engine接口 (8.5.6版本之前为Container接口,更加通用)。

既然Tomcat的Container可以表示不同的概念级别:Servlet引擎、虚拟主机、Web应用和Servlet,那么我们就可以将不同级别的容器作为处理客户端请求的组件,这具体由我们提供的服务器的复杂度决定。假使我们以嵌入式的方式启动Tomcat,且运行极其简单的请求处理,不必支持多Web应用的场景,那么我们完全可以只在Service中维护一个简化版的Engine ( 8.5.6之前甚至可以直接由Service维护一个Context)。当然,Tomcat的默认实现采用了图2-8这种最灵活的方式,只是,我们要了解Tomcat的模型设计理论上的可伸缩性,这也是一个中间件产品架构设计所需要重点关注的。

Tomcat总体架构(一)

此外,Tomcat的Container还有一个很重要的功能,就是后台处理。 在很多情况下,我们的Container需要执行一些异步处理,而且是定期执行,如每隔30秒执行一次,Tomcat对于Web应用文件变更的扫描就是通过该机制实现的。Tomcat针对后台处理,在Container上定义了backgroundProcess()方法,并且其基础抽象类( ContainerBase)确保在启动组件的同时,异步启动后台处理。因此,在绝大多数情况下,各个容器组件仅需要实现Container的background-Process()方法即可,不必考虑创建异步线程。

七、Lifecycle

在进一步深入细化应用服务器设计之前,我们希望从抽象和复用层面再审视一下当前的设计成果,使概念更加清晰,提供通用性定义用于应用服务器的统一管理。 我们很容易发现,所有组件均存在启动、停止等生命周期方法,拥有生命周期管理的特性。因此,我们可以基于生命周期管理进行一次接口抽象,如图2-9所示。 我们针对所有拥有生命周期管理特性的组件抽象了一个Lifecycle通用接口,该接口定义了生命周期管理的核心方法。

  • Init():初始化组件。
  • start():启动组件。
  • stop():停止组件。
  • destroy():销毁组件。

Tomcat总体架构(一)

同时,该接口支持组件状态以及状态之间的转换,支持添加事件监听器(LifecycleListener )用于监听组件的状态变化。如此,我们可以采用一致的机制来初始化、启动、停止以及销毁各个组件。如Tomcat核心组件的默认实现均继承自LifecycleNBeanBase抽象类,该类不但负责组件各个状态的转换和事件处理,还将组件自身注册为MBean,以便通过Tomcat的管理工具进行动态维护。

Tomcat中Lifecycle接口状态图如图2-10所示。 首先,每个生命周期方法可能对应数个状态的转换,以start()为例,即分为启动前、启动中、已启动,这3个状态之间自动转换(所有标识为auto的转换路径都是在生命周期方法中自动转换的,不再需要额外的方法调用)。

Tomcat总体架构(一)

其次,并不是每个状态都会触发生命周期事件,也不是所有生命周期事件均存在对应状态。状态与应用生命周期事件的对应如表2-1所示。

表2-1 Tomcat生命周期事件与状态映射

方法 状态 生命周期事件 init() 初始化中(INITIALIZING) 初始化前(BEFORE_INIT_EVENT) 已初始化(INITIALIZED) 初始化后(AFTER_INIT_EVENT) start() 启动前(STARTING_PREP) 启动前(BEFORE_START_EVENT) 启动中(STARTING) 启动(START_EVENT) 已启动(STARTED) 启动后(AFTER_START_EVENT) stop() 停止前(STOPPING_PREP) 停止前(BEFORE_STOP_EVENT) 停止中(STOPPING) 停止(STOP_EVENT) 已停止(STOPPED) 停止后(AFTER_STOP_EVENT) destroy() 销毁中(DESTROYING) 销毁前(BEFORE_DESTROY_EVENT) 已销毁(DESTROYED) 销毁后(AFTER_DESTROY_EVENT) 周期事件(PERIODIC_EVENT) 配置启动(CONFIGURE_START_EVENT) 配置停止(CONFIGURE_STOP_EVENT)

从表2-1中我们可以详细地看到每个生命周期方法影响的组件状态以及每个状态触发的事件。 此外,我们还注意到,Tomcat默认提供了3个与状态无关的事件类型,其中PERIODIC_EVENT主要用于Container的后台定时处理,每次调用后触发该事件。CONFIGURE_START_EVENT和CONFIGURE_STOP_EVENT的使用在后续章节中将会讲到。

Original: https://www.cnblogs.com/xysgo/p/16619323.html
Author: 菜阿
Title: Tomcat总体架构(一)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/601518/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 事务的7种传播行为

    转载:https://blog.csdn.net/soonfly/article/details/70305683 事务传播行为 事务传播行为指的是当一个事务方法被另一个事务方法调…

    数据库 2023年6月6日
    0120
  • 机器学习实战-决策树

    1.决策树的构造 1.1优缺点 优点: 计算复杂度不高:以ID3为例,每次运算都是基于某一列特征,特征计算完后,下次计算不考虑该最有特征,并且通过适当剪枝可以简化复杂度 输出结果易…

    数据库 2023年6月16日
    0103
  • mysql中group by,having,order by,limit,distinct的用法和简单的的多表查询

    group:组 by:通过 group by :通过….。分组group by列名:通过指定列来分组 一般情况下在题目中出现 “每个” &#82…

    数据库 2023年5月24日
    0105
  • 用户管理

    介绍Linux用户组的概念和对用户添加,删除和指定密码的基本操作 用户管理 Linux 系统是一个多用户多任务的操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一…

    数据库 2023年6月16日
    0128
  • Java压缩图片

    压缩图片 一、压缩原理 一张原始图像(1920×1080),如果每个像素32bit表示(RGBA),那么,图像需要的内存大小1920x1080x4 = 8294400 B…

    数据库 2023年6月6日
    097
  • 实现随机验证码

    Java实现随机验证码的生成 随机验证码: 法一:普通方法 核心逻辑: 1.定义一个String类型的变量存储验证码字符。 2.定义一个for循环,循环n次(n为验证码的所需要字符…

    数据库 2023年6月16日
    0122
  • 索引的树结构

    二分查找 二叉树 二叉平衡树 B-TREE :二叉平衡树的基础上,使加载一次节点,可以加载更多路径数据,同时把查询范围缩减到更小 缺点:业务数据的大小可能远远超过了索引数据的大小,…

    数据库 2023年5月24日
    069
  • Git

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    数据库 2023年6月16日
    098
  • 能尽量用数据库代替内存就用吧,减少整天担心内存问题

    游戏不好搞啊,设计的东西,能尽量简单就简单,代码太多判断就写死行了,反正它运行起来是对的就行了。 情形:09:00 昨天发生了很痛苦的一件事情,那就是游戏中data内存同步不到da…

    数据库 2023年6月14日
    072
  • MySQL学习(3)—MySQL常用命令

    ps:此随笔基于mysql 5.7.*版本。 准备 net start mysql 启动MySQL服务 net stop mysql 关闭MySQL服务 mysql [-h exi…

    数据库 2023年6月14日
    080
  • DASCTF7月misc–ez_forenisc

    内存镜像解析,得到bitlocker密钥 passware解析内存镜像,得到用户名密码 <span class=”ne-text”>550f37c7748e</s…

    数据库 2023年6月11日
    073
  • Eureka详解系列(三)–探索Eureka强大的配置体系

    通过前面的两篇博客,我们知道了:什么是 Eureka?为什么使用 Eureka?如何使用 Eureka?今天,我们开始来研究 Eureka 的源码,先从配置部分的源码开始看,其他部…

    数据库 2023年6月6日
    0206
  • Asp.NET core/net 5接口返回实体含有long/int64的属性序列后最后几位变为0的解决

    Asp.NET core /net 5接口返回实体含有long/int64的属性时,序列后最后几位变为0的。 不得不吐槽一下MS,这种事还有问题,NND。 解决方案在startup…

    数据库 2023年6月14日
    081
  • Background process terminated with code 1.

    使用vscode过程中,刷新maven依赖过程中,出现了如下错误信息: Background process terminated with code 1. 图1. maven插件…

    数据库 2023年6月14日
    079
  • mysql杂记漫谈

    Hello,大家好,这几天消失了一下,主要是线上系统出了点小bug和sql性能问题,在努力搬砖,就把之前的设计模式系列放了一下下,正好趁这个复习巩固了一下sql执行计划和sql优化…

    数据库 2023年6月14日
    078
  • liquibase新增字段注释导致表格注释同时变更bug记录

    liquibase是一个用于数据库变更跟踪、版本管理和自动部署的开源工具。它的使用方式方法可以参考官方文档或者其他人的博客,这里不做过多介绍。 1. 问题复现 在使用过程中发现了一…

    数据库 2023年6月14日
    0116
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球