7 Tomcat分析

tomcat7源码分析 tomcat7源码分析本篇分为六个部分: tomcat基本框架 tomcat启动流程简介 tomcat启动流程源码分析 tomcat处理一个请求过程分析 .jsp生成.java和.class流程分析 apache beachmark性能测试 一、tomcat基本框架由三部分组成: 组件架构:组件搭起房梁 基于JMX:JMX管理组件等 阅读详情

7 Tomcat分析

7.1.1 Tomcat的顶层结构

Tomcat中最顶层的容器叫Server,代表整个服务器,Server中包含至少一个Service,用于具体提供服务。Service主要包含两部分:Connector和Container。Connector用于处理连接相关的事情,并提供Socket与request、response的转换,Container用于封装和管理Servlet,以及具体处理request请求。一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但可以有多个Connectors(因为一个服务可以有多个连接,如同时提供http和https连接,也可以提供相同协议不同端口的连接).

在这里插入图片描述

Tomcat里的Server由org.apache.catalina.startup.Catalina来管理,Catalina是整个Tomcat的管理类,它里面的三个方法load、start、stop分别用来管理整个服务器的生命周期,

load方法用于根据conf/server.xml文件创建Server并调用Server的init方法进行初始化,

start方法用于启动服务器,stop方法用于停止服务器,start和stop方法在内部分别调用了Server的start和stop方法,load方法内部调用了Server的init方法,这三个方法都会按容器的结构逐层调用相应的方法,比如,Server的start方法中会调用所有的Service中的start方法,Service中的start方法又会调用所有包含的Connectors和Container的start方法,这样整个服务器就启动了,init和stop方法也一样,这就是Tomcat生命周期的管理方式,更加具体的内容见7.2节。Catalina还有个方法也很重要,那就是await方法,Catalina中的await方法直接调用了Server的await方法,这个方法的作用是进入一个循环,让主线程不会退出。

Tomcat的入口main方法在org.apache.catalina.startup.Bootstrap中。Bootstrap的作用类似一个CatalinaAdaptor,Bootstrap的作用类似一个CatalinaAdaptor,具体处理过程还是使用Catalina来完成的,这么做的好处是可以把启动的入口和具体的管理类分开,从而可以很方便地创建出多种启动方式**,每种启动方式只需要写一个相应的CatalinaAdaptor就可以了。

7.1.2 Bootstrap的启动过程

在init方法里初始化了ClassLoader,并用ClassLoader创建了Catalina实例,然后赋给catalinaDaemon变量,后面对命令的操作都要使用catalinaDaemon来具体执行。

对start命令的处理调用了三个方法:setAwait(true)、load(args)和start()。这三个方法内部都调用了Catalina的相应方法进行具体执行,只不过是用反射来调用的。

catalinaDaemon.getClass().getMethod(“start”, (Class [] )null);

method.invoke(catalinaDaemon, (Object [])null);

7.1.3 Catalina的启动过程

Catalina的启动主要是调用setAwait、load和start方法来完成的。setAwait方法用于设置Server启动完成后是否进入等待状态的标志,如果为true则进入,否则不进入;load方法用于加载配置文件,创建并初始化Server;start方法用于启动服务器。

load:根据conf/server.xml创建了Server对象,并赋值给server属性(具体解析操作是通过开源项目Digester完成的),然后调用了server的init方法

start:最后注册了关闭钩子并根据await属性判断是否进入等待状态;若进去等待,使用await方法直接调用了Server的await方法,Server的await方法内部会执行一个while循环,这样程序就停到了await方法,当await方法里的while循环退出时,就会执行stop方法,从而关闭服务器。

7.1.4 Server的启动过程

Server接口中提供addService(Serviceservice)、removeService(Service service)来添加和删除Service,Server的init方法和start方法分别循环调用了每个Service的init方法和start方法来启动所有Service。

Server的默认实现是org.apache.catalina.core.StandardServer,StandardServer继承自Lifecycle-MBeanBase,LifecycleMBeanBase又继承自LifecycleBase,init和start方法就定义在了LifecycleBase中,LifecycleBase里的init方法和start方法又调用initInternal方法和startInternal方法,这两个方法都是模板方法,由子类具体实现,所以调用StandardServer的init和start方法时会执行StandardServer自己的initInternal和startInternal方法,这就是Tomcat生命周期的管理方式。

StandardServer中的initInternal和startInternal方法分别循环调用了每一个service的start和init方法。

除了startInternal和initInternal方法,StandardServer中还实现了await方法,Catalina中就是调用它让服务器进入等待状态的。

await方法处理:大概逻辑是首先判断端口号port,然后根据port的值分为三种处理方法:

□port为-2,则会直接退出,不进入循环。

□port为-1,则会进入一个while(!stopAwait)的循环,并且在内部没有break跳出的语句,stopAwait标志只有调用了stop方法才会设置为true,所以port为-1时只有在外部调用stop方法才会退出循环。

□port为其他值,则也会进入一个while(!stopAwait)的循环,不过同时会在port所在端口启动一个ServerSocket来监听关闭命令,如果接收到了则会使用break跳出循环。

这里的端口port和关闭命令shutdown是在conf/server.xml文件中配置Server时设置的。

这时会在8005端口监听"SHUTDOWN"命令,如果接收到了就会关闭Tomcat。如果不想使用网络命令来关闭服务器可以将端口设置为-1。另外await方法中从端口接收到数据后还会进行简单处理,如果接收到的数据中有ASCII码小于32的(ASCII中32以下的为控制符)则会从小于32的那个字符截断并丢弃后面的数据。

7.1.5 Service的启动过程

Service的默认实现是org.apache.catalina.core.StandardService,StandardService也继承自LifecycleMBeanBase类,所以init和start方法最终也会调用initInternal和startInternal方法。

StandardService中的initInternal和startInternal方法主要调用container、executors、mapperListener、connectors的init和start方法。这里的container和connectors前面已经介绍过,mapperListener是Mapper的监听器,可以监听container容器的变化,executors是用在connectors中管理线程的线程池,在serverx.xml配置文件中有参考用法,不过默认是注释起来的,打开注释就可以看到其使用方法。

Connector就配置了一个叫tomcatThreadPool的线程池;

7.2 Tomcat的生命周期管理

7.2.1 Lifecycle接口

Tomcat通过org.apache.catalina.Lifecycle接口统一管理生命周期,所有有生命周期的组件都要实现Lifecycle接口。

Lifecycle接口一共做了4件事:

□定义了13个String类型常量,用于LifecycleEvent事件的type属性中,作用是区分组件发出的LifecycleEvent事件时的状态(如初始化前、启动前、启动中等)。这种设计方式可以让多种状态都发送同一种类型的事件(LifecycleEvent)然后用其中的一个属性来区分状态而不用定义多种事件,我们要学习和借鉴这种方式。

□定义了三个管理监听器的方法addLifecycleListener、findLifecycleListeners和remove-LifecycleListener,分别用来添加、查找和删除LifecycleListener类型的监听器。

□定义了4个生命周期的方法:init、start、stop和destroy,用于执行生命周期的各个阶段的操作。

□定义了获取当前状态的两个方法getState和getStateName,用来获取当前的状态,getState的返回值LifecycleState是枚举类型,里边列举了生命周期的各个节点,getStateName方法返回String类型的状态的名字,主要用于JMX中。

7.2.2 LifecycleBase

Lifecycle的默认实现是org.apache.catalina.util.LifecycleBase,LifecycleBase为Lifecycle里的接口方法提供了默认实现:

监听器管理是专门使用了一个LifecycleSupport类来完成的,LifecycleSupport中定义了一个LifecycleListener数组类型的属性来保存所有的监听器,然后并定义了添加、删除、查找和执行监听器的方法;addLifecycleListener、findLifecycleListeners和removeLifecycleListener方法分别调用了LifecycleSupport中的同名方法。添加LifecycleListener类;

生命周期方法中设置了相应的状态并调用了相应的模板方法,init、start、stop和destroy所对应的模板方法分别是initInternal、startInternal、stopInternal和destroyInternal方法,这四个方法由子类具体实现,所以对于子类来说,执行生命周期处理的方法就是initInternal、startInternal、stopInternal和destroyInternal;组件当前的状态在生命周期的四个方法中已经设置好了,所以这时直接返回去就可以了。

LifecycleSupport中还定义了处理LifecycleEvent事件的fireLifecycleEvent方法。new LifecycleEvent(lifecycle,type,data);后遍历所有监听器进行处理listeners.lifecycleEvent(event);

四个生命周期方法

四个生命周期方法的实现中首先判断当前的状态和要处理的方法是否匹配,如果不匹配就会执行相应方法使其匹配(如在init之前调用了start,这时会先执行init方法),或者不处理甚至抛出异常,如果匹配或者处理后匹配了,则会调用相应的模板方法并设置相应的状态。LifecycleBase中的状态是通过LifecycleState类型的state属性来保存的,最开始初始化值为LifecycleState.NEW。

init():如果开始的状态是LifecycleState.NEW,在具体初始化之前会将状态设置为LifecycleState.INITIALIZING,然后调用模板方法initInternal让子类具体执行初始化,初始化完成后将状态设置为LifecycleState.INITIALIZED。

invalidTransition方法专门用于处理不符合要求的状态.

start():在启动前先判断是不是已经启动了,如果已经启动了则直接返回,如果没有初始化会先执行初始化,如果是失败在状态就会调用stop方法进行关闭,如果状态不是前面那些也不是刚初始化完或者已经停止了则会抛出异常。如果状态是刚初始化完或者已经停止了,则会先将状态设置为LifecycleState.STARTING_PREP,然后执行startInternal模板方法调用子类的具体启动逻辑进行启动,最后根据是否启动成功设置相应的状态。

setStateInternal:除了设置状态还可以检查设置的状态合不合逻辑,并且会在最后发布相应的事件.

setStateInternal,通过check参数判断是否需要检查传入的状态,如果需要检查则会检查传入的状态是否为空和是否符合逻辑,最后将传入的状态设置到state属性,并调用fireLifecycleEvent方法处理事件

fireLifecycleEvent方法调用了LifecycleSupport的fireLifecycleEvent方法.

7.3 Container分析

7.3.1 ContainerBase的结构

Container是Tomcat中容器的接口,通常使用的Servlet就封装在其子接口Wrapper中。Container一共有4个子接口Engine、Host、Context、Wrapper和一个默认实现类ContainerBase,每个子接口都是一个容器,这4个子容器都有一个对应的StandardXXX实现类,并且这些实现类都继承ContainerBase类。另外Container还继承Lifecycle接口,而且ContainerBase间接继承LifecycleBase,所以Engine、Host、Context、Wrapper 4个子容器都符合前面讲过的Tomcat生命周期管理模式.

Tomcat7.0源码分析——请求原理分析(下) 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过《Tomcat7.0源码分析——请求原理分析(上)》和《Tomcat7.0源码分析——请求原理分析(中)》。在《Tomcat7.0源码分析——请求原理分析(中)》一文我简单讲到了Pipeline,但并未完全展开,本文将从Pipeline开始讲解请求原理的剩余内容。 阅读详情

相关推荐

Tomcat7.0源码分析——请求原理分析(上)

谈起Tomcat的诞生,最早可以追溯到1995年。近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉。很多人早期的J2EE项目,由程序员自己实现Jsp页面或者Servlet接受请求,后来借助Struts1、Struts2、Spring等中间件后,实际也是利用Filter或者Servlet处理请求,大家肯定要问了,这些Servlet处理的请求来自哪里?Tomcat作为Web服务器是怎样将HTTP请求交给Servlet的呢?

beliefer的博客 3万+

Tomcat7.0源码分析——启动与停止服务原理

熟悉Tomcat的工程师们,肯定都知道Tomcat是如何启动与停止的。对于startup.sh、startup.bat、shutdown.sh、shutdown.bat等脚本或者批处理命令,大家一定知道改如何使用它,但是它们究竟是如何实现的,尤其是shutdown.sh脚本(或者shutdown.bat)究竟是如何和Tomcat进程通信的呢?本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程。

beliefer的博客 1万+

Tomcat7.0源码分析——server.xml文件的加载与解析

作为Java程序员,对于tomcat的server.xml想必都不陌生。本文基于Tomcat7.0的Java源码,对server.xml文件是如何加载和解析进行分析。

beliefer的博客 1万+

深入理解Tomcat 7.0.42源码:在Eclipse中的实现与分析

Apache Tomcat作为Java EE容器,具有清晰的模块划分。其源码结构主要分为以下几个部分:核心引擎(Catalina)、连接器(Connectors)、Web服务器(Coyote)、资源管理(Jasper)等。Tomcat作为一款开源的Servlet容器,其内部架构设计使得它能够高效地处理HTTP请求并管理Web应用。在学习和部署Tomcat时,了解其关键组件和它们之间的交互至关重要。Tomcat的每个组件都有其特定的功能和配置,下面详细介绍几个关键组件。Server。

weixin_35761094的博客 1036

[医学图像分割综述] Medical Image Segmentation Using Deep Learning: A Survey

本综述有两个独创之处,首先,与传统的调查方法直接将医学图像分割的文献划分为多个组,并对每个组详细介绍文献的方法相比,我们将目前流行的文献按照从粗到细的多层次结构进行分类。其次,本文重点研究了监督学习和弱监督学习方法,但未包括无监督方法,这种方法目前在医学图像领域并不流行。对于监督学习方法,我们从骨干网络的选择、网络块的设计和损失函数的改进三个方面对文献进行了分析。对于弱监督学习方法,我们分别根据数据增强,迁移学习和交互式分割研究文献。与已有的调查相比,本次调查的文献分类与以往有很大的不同,更便于读者了解相关

qq_38932073的博客 4万+

数字IC后端PR阶段Innovus,ICC,ICC2修复short万能脚本分享

数字IC后端PR阶段Innovus,ICC,ICC2修复short万能脚本分享

weixin_37584728的博客 3458

SCCM部署教程:(3)SCCM安装

这两则摘要介绍了WSUS和SCCM的安装步骤: WSUS安装:通过服务器管理器添加"Windows服务器更新服务"角色,选择SQL数据库并指定安装路径,验证数据库连接后完成安装。 SCCM安装:先运行预检工具Prereqchk.exe,选择主站点安装类型,配置语言、站点代码和名称,设置SQL数据库连接参数(保留默认端口4022),选择通信方法和系统角色(管理点和分发点),最后完成约1小时的安装过程。 两则安装指南都强调要确保数据库配置与前期准备一致,并提供了关键配置选项的说明。

小V锅的专栏 915

基于51单片机扫地机器人(全套Proteus仿真+原理图+程序+说明书)

(内含源程序代码,原理图,仿真,讲解视频,元件清单等,【精品】值得推荐!!!扫地机器人是以单片机为主控制器。通过单片机控制小车行驶、除尘、蜂鸣。扫地机器人使用双电机驱动,以提高整车运动的平稳性;在智能车进驶过程中,采用双超声波模块实现避障。

2301_76434107的博客 1895

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍_nbiot ntn

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!” />你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!更多资料点击此处获qu!!

2401_83703866的博客 3167

Apollo 9.0 速度非线性规划算法 – piecewise jerk speed nonlinear optimizer Ⅰ

二次规划的速度规划算法(PiecewiseJerkSpeedOptimizer)的存在两个问题: 这里以一张图来说明上面的问题,假设存在一个实际限速区间(或曲率很大需要降速的区间)[S1, S2],PiecewiseJerkSpeedOptimizer的做法是根据动态规划的st曲线(黑色),找到具体的时间区间[T1, T2],然后对区间[T1, T2]内所有的点施加约束或惩罚。但是二次规划平滑后的曲线(黄色)发生了变化,那么限速区间[S1, S2]对应的时间区间[T1, T2]也发生了变化,所以实际应该是对

WaiNgai 333

2024.12.29 【RNA-seq】Rawdata数据缺失问题与解决方案

Fastq格式是一种用于存储高通量测序数据的文件格式,包含序列和相应的质量信息。第一行以开头,后接序列标识符;第二行是测序的DNA序列;第三行以开头,可能会跟随序列标识符;第四行是对应的质量值,以ASCII字符表示。Rawdata的数据完整性通常情况下是没有问题的,但我们仍然需要对下机数据进行验证,确保后续分析的正常进行,好的分析习惯可以提高整体的分析效率,避免很多不必要的麻烦。

1112

扣子(Coze)搭建智能体完整实战指南 —— 从零基础入门到写小说及其他需求扩展开发

随着大语言模型进入应用爆发期,我们正在经历从“寻找提示词”向“构建智能体”的范式转移。扣子(Coze)作为字节跳动推出的一站式AI智能体开发与运营平台,极大地降低了AI应用开发的门槛,让非技术人员也能快速搭建具备感知、决策、行动能力的智能体。 本文将手把手带你从零开始,在扣子平台上搭建一个功能完备的**小说创作智能体**,并基于此展示如何将同一套架构扩展到其他需求场景。无论你是写作爱好者、内容创作者,还是希望用AI赋能日常工作的职场人士,这套完整的技术方案都将帮助你快速上手。

huanghm88的专栏 638

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

上一篇: 线程安全与锁优化
下一篇: springcloud介绍
青葱暖咖啡
博客等级 码龄14年 0粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值