Tomcat

作者: 麦大大吃不胖 | 来源:发表于2021-02-20 00:21 被阅读0次

    by shihang.mai

    1. Tomcat结构

    y4FKsO.png
    1. 一个请求发送到Tomcat之后,首先经过Service然后会交给我们的Connector,Connector用于接收请求并将接收的请求封装为Request和Response来具体处理,Request和Response封装完之后再交由Container进行处理,Container处理完请求之后再返回给Connector,最后在由Connector通过Socket将处理的结果返回给客户端

    2. 我们来说说Connector

    Connector中包括一个ProtocolHandler,不同的连接类型就有不同的ProtocolHandler。比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的

    ProtocolHandler中主要包含

    • Endpiont

      用来处理底层Socket的网络连接,正因如此,它实现TCP/IP协议

      • Acceptor

        用于监听请求

      • Handler

        用于处理接收到的Socket,处理完后调用Processor处理

      • AsyncTimeout

        用于检查异步Request的超时

    • Processor

      用于将Endpoint接收到的Socket封装成Request,正因如此,它实现HTTP协议

    • Adapter

      将Request适配到Servlet容器进行具体的处理

    1. 请求交给Container后,我们来说说Container

    Container处理请求是使用Pipeline-Valve管道来处理的,而每个Pipeline最后都有一个BaseValve,并且这个BaseValve会调用下层的Pipeline

    EnginePipleline

    EngineValve1.....EngineValveN.....StandardEngineValve->

    HostPipleline

    HostValve1.....HostValveN......StandardHostValve->

    ContextPipleline

    ContextValve1.....ContextValveN......StandardContextValve->

    WapperPipleline

    WapperValve1.....WapperValveN......StandardWapperValve

    在StandardWapperValve创建FilterChain,这个FilterChain包含请求对应的Filter和Servlet,调用FilterChain.doFilter依次Filter和Servlet处理请求

    当所有的Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端

    2. Tomcat启动原理

    1. Tomcat启动入口Bootstrap.main(),new Bootstrap(),调用init(),Init()方法里面先初始化ClassLoader,然后用ClassLoader.load入Catalina
    2. 判断main方法传入的参数,如果参数为空,默认为start.在start命令的处理调用的时候有三个方法:setAwait、load
      、start。这三个方法在内部调用了Clatalina的相应的方法进行具体的执行,只不过是用反射来调用的
    public static void main(String args[]) {
    
            synchronized (daemonLock) {
                if (daemon == null) {
                    // Don't set daemon until init() has completed
                    Bootstrap bootstrap = new Bootstrap();
                    try {
                        bootstrap.init();
                    } catch (Throwable t) {
                        handleThrowable(t);
                        t.printStackTrace();
                        return;
                    }
                    daemon = bootstrap;
                } else {
                    // When running as a service the call to stop will be on a new
                    // thread so make sure the correct class loader is used to
                    // prevent a range of class not found exceptions.
                    Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
                }
            }
    
            try {
                String command = "start";
                if (args.length  0) {
                    command = args[args.length - 1];
                }
    
                if (command.equals("startd")) {
                    args[args.length - 1] = "start";
                    daemon.load(args);
                    daemon.start();
                } else if (command.equals("stopd")) {
                    args[args.length - 1] = "stop";
                    daemon.stop();
                } else if (command.equals("start")) {
                    daemon.setAwait(true);
                    daemon.load(args);
                    daemon.start();
                    if (null == daemon.getServer()) {
                        System.exit(1);
                    }
                } else if (command.equals("stop")) {
                    daemon.stopServer(args);
                } else if (command.equals("configtest")) {
                    daemon.load(args);
                    if (null == daemon.getServer()) {
                        System.exit(1);
                    }
                    System.exit(0);
                } else {
                    log.warn("Bootstrap: command \"" + command + "\" does not exist.");
                }
            } catch (Throwable t) {
                // Unwrap the Exception for clearer error reporting
                if (t instanceof InvocationTargetException &&
                        t.getCause() != null) {
                    t = t.getCause();
                }
                handleThrowable(t);
                t.printStackTrace();
                System.exit(1);
            }
        }
    
    1. 方法介绍

      • setAwait方法用于设置Server启动完成后是否进入等待状态的标志,如果为true则进入,否则不进入;
      • load方法用于加载server.xml配置文件,并加载Server、Service、Connector、Container、Engine、Host、Context、Wrapper一系列的容器;
      • start用于启动服务器
    2. 调用Catalina.start()方法

      会调用Server.start()方法会调用LifecycleBase的start(),而LifecycleBase的start()方法中主要执行了init和start方法

      • init方法,它会先后执行Server、Service、Engine、Excutor、MapperListener、Connector的initInternal方法

      • start方法,它会先后执行Server、Service、Engine、Excutor、MapperListener、Connector的startInternal方法

      • 当然它们会伴随状态位的变化,状态变化如下

        MapperListener是Mapper的监听器,用来监听Container容器的变化;Executors是用在Connectors中管理线程的线程池

      流程

    参考博客

    https://blog.csdn.net/xlgen157387/article/details/79006434
    

    相关文章

      网友评论

          本文标题:Tomcat

          本文链接:https://www.haomeiwen.com/subject/xwbzxltx.html