【tomcat】tomcat系统架构以及核心启动流程

news2024/11/27 14:35:22

对于web后端开发工程师来说,tomcat作为一个应用服务器框架本质上就是一个HTTP服务+Servlet容器。研究过spring、spring mvc源码的同学应该了解,spring mvc其实就是基于Servlet规范实现的请求的转发路由、转发处理。而Spring和SpringMVC就是通过web.xml文件中的事件监听器ContextListener加载Spring容器,然后在加载SpringMVC子容器。

所以带着几个问题,去学习tomcat的原理,本篇先聊聊基础架构,以及核心的启动流程。

  • 基本架构如何,以及各个组件如何功能
  • 启动的核心流程
  • 处理请求的核心流程
  • tomcat的是如何打破双亲委派模型,进行的类加载
  • tomcat的线程模型
  • tomcat的性能调优

在这里插入图片描述

tomcat系统架构

在这里插入图片描述
对于tomcat来说,比较重要的就是server.xml文件

1 <Server> //顶层组件,可以包括多个Service
2 <Service> //顶层组件,可包含一个Engine,多个连接器
3 <Connector/> //连接器组件,代表通信接口
4 <Engine> //容器组件,一个Engine组件处理Service中的所有请求,包含多个Host
5 <Host> //容器组件,处理特定的Host下客户请求,可包含多个Context
6 <Context/> //容器组件,为特定的Web应用处理所有的客户请求
7 </Host>
8 </Engine>
9 </Service>
10 </Server>

在这里插入图片描述
Connector 连接器:对外交流
Container 容器:内部处理
Server:负责和管理启动多个service,加痛8005端口的shutdown命令。关闭整个容器

启动流程

启动类就是BootStrap的main方法。

init

在这里插入图片描述
初始化反射生成一个Catalina对象。这里有类加载器的操作,先不介绍,后面在进行单独讲解。

daemon.load(args);

在这里插入图片描述
反射调用catalina.load()方法

 digester.parse(inputSource); // 解析server.xml文件 构建对象
getServer().init(); // 初始化 可以看到这里是StandardServer

在这里插入图片描述

public final class StandardServer extends LifecycleMBeanBase implements Server 
// 因为StandardServer继承了LifeCycleMBeanBase 先调用父类的init()


public final synchronized void init() throws LifecycleException {
    // 不是new 不能调用init
    if (!state.equals(LifecycleState.NEW)) {
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }

    try {
        // 初始化之前 状态变更为init
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        // 模版方法 拓展使用
        initInternal();
        // 初始化完成
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    } catch (Throwable t) {
        // 初始化异常 修改成 公共逻辑
        handleSubClassException(t, "lifecycleBase.initFail", toString());
    }
}


for (Service service : services) {
    // Service组件初始化
    service.init();
}


这里只有一个对象,所以对StandardService进行初始化,在初始化Service的时候,发现需要先初始化engine

在这里插入图片描述
在这里插入图片描述

if (engine != null) {
     // 1.Engine组件, 即servlet容器 初始化
     // 创建了一个线程池用于后续start流程中的 Host 的启动
     engine.init();
 }


// Initialize our defined Connectors
synchronized (connectorsLock) { // 加锁操作
    for (Connector connector : connectors) {

        // 2. Connector组件 初始化
        // endpoint 绑定端口
        connector.init();
    }
}


 // TODO 重点关注 Endpoint 的端口绑定与 NIO的监听
protocolHandler.init();


 // Endpoint 组件的初始化
endpoint.init();

// 三种实现, 默认 NioEndpoint
 // BioEndpoint
 // NioEndpoint
 // Nio2Endpoint
 bind();


// NIO之 获取通道 SocketChannel
serverSock = ServerSocketChannel.open();

socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());

// NIO之 绑定端口( IP:PORT )
serverSock.socket().bind(addr,getAcceptCount());

在这里插入图片描述

总结下,其实初始化的过程就是把一些基础的东西进行加载。主要是绑定8090端口。

start

在这里插入图片描述
这里执行start方法,会去反射调用catalina.start()方法

 // TODO 3.真正启动
 daemon.start();
 
  Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
 method.invoke(catalinaDaemon, (Object [])null);

// 执行启动
getServer().start();

// 循环遍历service
for (Service service : services) {
    // 启动所有的 service
    service.start();
}


synchronized (engine) {
      // 启动 Engine 子容器
      engine.start();
}

// 可以看到这里通过线程池进行异步处理
for (Container child : children) {
    // 这就是 Engine init 过程中构建好的线程池
    // 这个线程池是在实例化 Engine 时给 Host 用的
    // 处理逻辑在 StandardHost 中的 startInternal
    results.add(startStopExecutor.submit(new StartChild(child)));
}

open();

 // 启动 Connector 组件
connector.start();
protocolHandler.start();
endpoint.start();

// 创建线程池
public void createExecutor() {
       internalExecutor = true;
       TaskQueue taskqueue = new TaskQueue();
       TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
       executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
       taskqueue.setParent( (ThreadPoolExecutor) executor);
   }


// 等待
public void await() {
    getServer().await();
}

在这里插入图片描述

小结

其实就是三个流程,初始化、解析文件、启动。
而最终的处理请求由acceptor\poller\worker 来处理。具体的流程在流程图中。
在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DINO-DETR

DINO-DETR DETR收敛慢的问题1. Contrastive DeNoising Training(对比方法降噪训练)2. Mixed Query Selection(混合查询选择方法对锚点进行初始化)3. Look Forward Twice(两次前向方法)==DINO模型的传播过程,以及部分模块的改进==DETR收敛慢的问题 PnP-DETR(ICCV 2021) 改进了…

同时使用接口文档swagger和knife4j

项目场景&#xff1a; springboot项目中同时使用接口文档swagger和knife4j 问题描述 在实体类中设置了字段必填的属性&#xff0c;在访问接口文档时出现异常 实体类关键代码片段 /*** 部门表 sys_dept*/ public class SysDept extends BaseEntity {private static final lo…

大聪明教你学Java | 深入浅出聊 Kafka

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

2024年6月23日 十二生肖 今日运势

小运播报&#xff1a;2024年6月23日&#xff0c;星期日&#xff0c;农历五月十八 &#xff08;甲辰年庚午月戊午日&#xff09;&#xff0c;法定节假日。今天国际奥林匹克日&#xff0c;坚不可摧的意志&#xff0c;披荆斩棘的豪情&#xff0c;永远值得拥有&#xff01; 红榜生…

YOLOv8改进 | SPPF | 双通道特征处理的池化结构——SPPFCSPC【全网独家】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容&#xff0c;内含各种Head检测头、损失函数Loss、…

LLM主流架构和模型

本文参考自https://github.com/HqWu-HITCS/Awesome-Chinese-LLM?tabreadme-ov-file和Huggingface中的ModelCard&#xff08;https://huggingface.co/&#xff09; LLM主要类别架构 LLM本身基于transformer架构。自2017年&#xff0c;attention is all you need诞生起&#x…

P1223 排队接水

题目描述 有 &#x1d45b; 个人在一个水龙头前排队接水&#xff0c;假如每个人接水的时间为 &#x1d447;&#x1d456;&#xff0c;请编程找出这 &#x1d45b; 个人排队的一种顺序&#xff0c;使得 &#x1d45b;个人的平均等待时间最小。 输入格式 第一行为一个整数 &a…

C++ | Leetcode C++题解之第169题多数元素

题目&#xff1a; 题解&#xff1a; class Solution { public:int majorityElement(vector<int>& nums) {int candidate -1;int count 0;for (int num : nums) {if (num candidate)count;else if (--count < 0) {candidate num;count 1;}}return candidate;…

根据状态转移写状态机-二段式

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 描述 题目描述&#xff1a; 如图所示为两种状态机中的一种&#xff0c;请根据状态转移图写出代码&#xff0c;状态转移线上的0/0等表示的意思是过程中data/flag的值。 要求&#xff1a; 1、 必须使用对应类型的状…

Django 条件判断模板标签

1&#xff0c;条件判断模板标签 1. 2 {% if %} 标签 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 --> {% endif %} 1. 3 {% if %} 与 {% else %} 组合 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 -->…

Ubuntu使用 NVIDIA GPU 和 CUDA 设置 LLM 的训练、微调和推理

0.引言 近年来&#xff0c;人工智能领域取得了令人瞩目的进步&#xff0c;其核心是图形处理单元&#xff08;GPU&#xff09;和并行计算平台的强大组合。 大模型如 GPT、BER能够理解和生成具有前所未有的流畅性和连贯性的类人文本。然而&#xff0c;训练这些模型需要大量的数据…

外卖APP开发详解:从同城O2O系统源码开始

近期&#xff0c;从事软件开发的小伙伴们都在讨论外卖APP&#xff0c;热度非常之高&#xff0c;所以小编今天将与大家一同探讨同城O2O系统源码、外卖APP开发。 一、外卖APP开发的前期准备 了解目标用户的需求&#xff0c;分析竞争对手的优劣势&#xff0c;明确自身的市场定位。…

算法金 | 统计学的回归和机器学习中的回归有什么差别?

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 统计学中的回归 目标&#xff1a; 主要用于解释和推断自变量&#xff08;independent variables&#xff09;和因变量&#xff08;de…

免杀笔记 ---> C语言

这次的更新可能有点慢&#xff0c;因为这段时间也比较忙&#xff0c;加上C语言还得和汇编结合&#xff0c;导致小编一个知识点总是得反复揣摩&#xff08;太菜了&#xff09;&#xff0c;所以免杀的更新篇幅长度可能会达到两个月和三个月&#xff0c;但是小编能保证&#xff0c…

中国科学院西北生态环境资源研究院联合多单位在《PNAS》发文:气候变暖对多年冻土区地上与地下生物量分布的影响

文章简介 论文名称&#xff1a;Changes in above-versus belowground biomass distribution in permafrost regions in response to climate warming&#xff08;气候变暖对多年冻土区地上与地下生物量分布的影响&#xff09; 第一作者及单位&#xff1a;贠汉伯&#xff08;研…

Hadoop archive

Index of /dist/hadoop/commonhttps://archive.apache.org/dist/hadoop/common/

【Git】--Part3--远程操作 配置 标签管理

1. 远程仓库 Git 是分布式版本控制系统&#xff0c;同⼀个 Git 仓库&#xff0c;可以分布到不同的机器上。怎么分布呢&#xff1f; 最早&#xff0c;肯定只有⼀台机器有⼀个原始版本库&#xff0c;此后&#xff0c;别的机器可以 “克隆” 这个原始版本库&#xff0c;⽽且每台机…

css grid实现九宫格布局

常见的九宫格布局可以使用flex布局实现&#xff0c;但是flex布局有个致命的缺陷&#xff0c;比如3行3列的布局&#xff0c;当第不足3个元素的时候&#xff0c;元素依然是平局平铺的&#xff0c;这样就不满足九宫格的效果&#xff0c;这种情况&#xff0c;使用grid布局可以轻松搞…

web中间件漏洞-Jenkins漏洞-弱口令、反弹shell

web中间件漏洞-Jenkins漏洞-弱口令、反弹shell Jenkins弱口令 默认用户一般为jenkins/jenkins 使用admin/admin123登陆成功 Jenkins反弹shell 格式为 println"命令".execute().text 在/tmp目录中生成shell.sh文件&#xff0c;并向其中写入反弹shell的语句 new…

猫头虎分享已解决Bug || Null Pointer Exception: `java.lang.NullPointerException`

猫头虎分享已解决Bug || Null Pointer Exception: java.lang.NullPointerException &#x1f63a;&#x1f42f; 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程…