ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深入理解Tomcat

2021-10-23 12:03:37  阅读:117  来源: 互联网

标签:容器 调用 tomcat Tomcat 理解 线程 深入 加载


目录

02 HTTP 必知必会

因为http是无状态的 所以出现了,cookies 存储状态信息,但是存储在本地不安全,这么也就有了 session,存储在服务器端,配合cooikes来进行标识;

03 Servlet容器

Servlet其实是一个接口,定义了servlet规范。一个http请求 到服务器的工作流程如下:
1、将请求信息封装成ServletRequest
2、调用servlet的service方法
3、如果不存在,那么就调用init方法创建
4、调用service方法,然后返回reponse对象,返回给客户端
servlet容器,web容器,spring容器,springmvc容器的区别;


SpringMVC的容器直接管理跟DispatcherServlet相关的Bean,也就是Controller,ViewResolver等,并且SpringMVC容器是在DispacherServlet的init方法里创建的。而Spring容器管理其他的Bean比如Service和DAO。
并且SpringMVC容器是Spring容器的子容器,所谓的父子关系意味着什么呢,就是你通过子容器去拿某个Bean时,子容器先在自己管理的Bean中去找这个Bean,如果找不到再到父容器中找。但是父容器不能到子容器中去找某个Bean。父容器 不能依赖子容器;

上图来源于网络

04 Tomcat系统架构-连接器

tomcat设计了两个核心组件:连接器Connector, 容器Container;连接负责对外交流,容器负责内部处理;

连接器的基本功能:
1、监听网络端口
2、接收网络请求连接
3、将请求解析转换为 Tomcat Request 对象
4、将Tomcat Request 转换为 Servlet Request
**5、调用Servlet 获得 Servlet Response **
6、将获得的结果转换,响应返回给前端

根据上述功能,Tomcat 就把它抽象成了三个核心类,EndPoint 、Process、Adapter 来分别处理

  • 网络通信
  • 应用层协议解析
  • Tomcat Request 到 Servlet的转换

组件之间通过接口进行交互,封装变化,将系统中经常变化的部分,和稳定的部分进行隔离;有助于增加复用性,并降低系统的耦合度;
其交互处理的逻辑如下:

![](https://www.icode9.com/i/ll/?i=img_convert/5e2024ddb47977c566fb9ecf32972c16.png#clientId=u604cc54a-cf5a-4&from=paste&height=266&id=u10206821&margin=[object Object]&name=image.png&originHeight=532&originWidth=1450&originalType=binary&ratio=1&size=208315&status=done&style=none&taskId=uab577043-6cae-4a92-9ed6-fa2cfa67b4a)

4.1 ProtocolHandler 组件
这个组件内部包含两个组件,EndPoint 和 Processor;
**EndPoint: **负责通信的端点,是具体的Socket接收和发送的处理器,该组件是实现Tcp/Ip 协议的(内部有个线程池处理请求)
**Processor:**用来实现 HTTP 协议,Processor 接收来自 EndPoint 的 Socket,读取字节流解析成 Tomcat Request 和Response 对象,并通过 Adapter 将其提交到容器处理,Processor 是对应用层协议的抽象。

EndPoint 负责底层 Socket通信,Proccesor 负责应用层协议解析。连接器通过适配器 Adapter 转换调用容器。

05 Tomcat系统架构-容器

容器的层次结构,Tomcat设计了4种容器,分别是Engin 、Host、Context 、Wapper

他们是一个包含关系。Tomcat 通过一种分层的架构,使得 Servlet 容器具有很好的灵活性。

  • Context 表示一个 Web 应用程序;
  • Wrapper 表示一个 Servlet,一个 Web 应用程序中可能会有多个 Servlet;
  • Host 代表的是一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序;
  • Engine 表示引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine。


上图展示了,根据Url是如何找到对应的wapper进行处理;

连接器中Adapter 会调用容器的 Service 方法来执行 Servlet,最先拿到请求的是 Engine 容器,Engine 容器对请求做一些处理后,会把请求传给自己子容器 Host 继续处理,依次类推,最后这个请求会传给 Wrapper 容器,Wrapper 会调用最终的 Servlet 来处理。那么这个调用过程具体是怎么实现的呢?
答案是使用 Pipeline-Valve 管道。

  • Pipeline-Valve 是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将再调用下一个处理者继续处理。


在连接器里 会有一个触发调用 Engine的一个 value,然后以责任链的模式不断传递,Wrapper 容器的最后一个 Valve 会创建一个 Filter 链,并调用 doFilter() 方法,最终会调到 Servlet 的 service 方法

06 Tomcat请求过程流转


组件是如何创建,初始化,销毁的呢,管理他们的生命周期是一个很关键的问题?如何实现一键启动?
答:tomcat的核心组件都抽象出公共的部分 lifecycle接口其中定义了:init()、start()、stop() 和 destroy()这么几个核心方法;在父组件中创建的时候需要调用子组件的init方法。所以只要调用顶层的 Service的init方法,整个tomcat就启动了。

这是lifecyle的模版方法

 @Override
    public final synchronized void init() throws LifecycleException {
       // 1、判断状态
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }

        try {
            // 2 触发 INITIALIZING 事件的监听器
            setStateInternal(LifecycleState.INITIALIZING, null, false);
           
            // 3 调用子类初始化方法
            initInternal();
            
            //  触发 INITIALIZED 事件的监听器 
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
           
        }
    }

Tomcat 自定义了一些监听器,这些监听器是父组件在创建子组件的过程中注册到子组件的。比如 MemoryLeakTrackingListener 监听器,用来检测 Context 容器中的内存泄漏,这个监听器是 Host 容器在创建 Context 容器时注册到 Context 中的。我们还可以在 server.xml 中定义自己的监听器,Tomcat 在启动时会解析 server.xml,创建监听器并注册到容器组件。

整体类图:

07 Tomcat启动流程

通常我通过执行tomcat bin下的 startup.sh 脚本启动tomcat,那么tomcat到底是如何启动的呢? 具体流程如下:

7.1 Catalina 组件

它是个启动类,通过解析server.xml ,创建相应的组件,并调用server的start方法,向下传递启动。Catalina是一个管理则者的身份,它还需要处理各种异常场景,当发生 ctrl+ c 强制关闭时,是如何释放资源的。Catalina在JVM中注册了一个关闭的钩子。

public void start() {

        if (getServer() == null) {
            load();
        }

        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();

        // Start the new server
        try {
            getServer().start();
        } catch (LifecycleException e) {
            
            return;
        }


        // Register shutdown hook
        if (useShutdownHook) {
            if (shutdownHook == null) {
                shutdownHook = new CatalinaShutdownHook();
            }
            // 注册一个jvm的回调函数;内部其实是进行资源的释放和清理
            Runtime.getRuntime().addShutdownHook(shutdownHook);
        }
		
    // 监听停止请求
        if (await) {
            await();
            stop();
        }
    }


7.2 Server 组件

Server的具体实现类是StandServer.这个组件会管理 service的生命周期。在server内部维护着多个service组件。还有一个重要的任务就是,启动Socket来监听停止端口。

7.2 Service 组件

Service组件的具体实现类是StandardService,


    /**
     *
     * 这是service 实例
     *
     */
    private Server server = null;



    /**
     *
     * 连接器
     */
    protected Connector connectors[] = new Connector[0];
    private final Object connectorsLock = new Object();

    /**
     * engine容器
     *
     */
    private Engine engine = null;


@Override
    protected void startInternal() throws LifecycleException {

   
        // 1、触发启动监听器
        setState(LifecycleState.STARTING);

        //  2、启动引擎
        if (engine != null) {
            synchronized (engine) {
                engine.start();
            }
        }


        // 3、mapper监听器 热加载部署
        mapperListener.start();

        
        // 4、连接器的启动 内部会启动子组建 如:endoint组件
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                        connector.start();
                }
            }
        }
    }

service作为管理者,最重要的是维护其他组件的生命周期;启动组件时要维护依赖关系。

7.3 Engine组件

engine组件的本质是一个容器,它继承了ContainerBase基类,并实现了Engine接口

08 NioEndpoint组件:Tomcat如何实现非阻塞I/O?

uninx下有5种IO模型:同步阻塞IO, 同步非阻塞IO, IO多路复用,信号驱动IO, 异步IO。见:

标签:容器,调用,tomcat,Tomcat,理解,线程,深入,加载
来源: https://blog.csdn.net/weixin_43732955/article/details/120919147

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有