• tomcat启动(六)Catalina分析-StandardServer.start()


    从链接

    Tomcat中组件的生命周期管理公共接口Lifecycle

    可以知道调用的是StandardServer.startInternal()

     @Override
        protected void startInternal() throws LifecycleException {
    
            fireLifecycleEvent(CONFIGURE_START_EVENT, null);
            setState(LifecycleState.STARTING);
    
            globalNamingResources.start();
    
            // Start our defined Services
            synchronized (servicesLock) {
                for (int i = 0; i < services.length; i++) {
                    services[i].start();
                }
            }
        }

    1、首先用fireLifecycleEvent()方法发送CONFIGURE_START_EVENT=“config_start”事件

    这个事件会被NamingContextListener监听器接收,会为StandardServer的属性globalNamingResources设置监听器为this当前类NamingContextListener

    然后生成一个NamingContext命名上下文对象(这个上下文对象联系着JNDI Context)

    为StandardServer设置private   javax.naming.Context   globalNamingContext的值

    2、

    globalNamingResources.start();这里也发送的一个CONFIGURE_START_EVENT=“config_start”事件

    设置状态为starting

    /**
     * Holds and manages the naming resources defined in the J2EE Enterprise
     * Naming Context and their associated JNDI context.
     *保存并管理J2EE企业命名上下文中定义的命名资源及其关联的JNDI上下文
     * @author Remy Maucherat
     */
    public class NamingResourcesImpl extends LifecycleMBeanBase
            implements Serializable, NamingResources 

    3、services[i].start();

    这里调用StandardService.startInternal()

    /**
         * Start nested components ({@link Executor}s, {@link Connector}s and
         * {@link Container}s) and implement the requirements of
         * {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
         *启动嵌套组件StandardThreadExecutor,Connector和StandardEngine
         * @exception LifecycleException if this component detects a fatal error
         *  that prevents this component from being used
         */
        @Override
        protected void startInternal() throws LifecycleException {
    
            if(log.isInfoEnabled())
                log.info(sm.getString("standardService.start.name", this.name));
            setState(LifecycleState.STARTING);
    
            // Start our defined Container first
            if (container != null) {
                synchronized (container) {
                    container.start();
                }
            }
    
            synchronized (executors) {
                for (Executor executor: executors) {
                    executor.start();
                }
            }
    
            mapperListener.start();
    
            // Start our defined Connectors second
            synchronized (connectorsLock) {
                for (Connector connector: connectors) {
                    try {
                        // If it has already failed, don't try and start it
                        if (connector.getState() != LifecycleState.FAILED) {
                            connector.start();
                        }
                    } catch (Exception e) {
                        log.error(sm.getString(
                                "standardService.connector.startFailed",
                                connector), e);
                    }
                }
            }
        }

    1、container.start();

     调用的是StandardEngine.startInternal()

     2、executor.start();

    执行提交的Runnable任务的对象。这个接口提供了一种将任务提交与每个任务如何运行的机制解耦的方法,包括线程使用的细节,调度等。通常使用Executor而不是显式地创建线程。

     StandardThreadExecutor:线程执行类。可以看做线程池对象

    3、mapperListener.start();

    调用MapperListener.startInternal()

    用一个变量Mapper mapper持有Host,为StandardEngine和其子Container设置监听器为当前类MapperListener

    4、connector.start();

    调用Connector。startInternal()

    /**
         * Begin processing requests via this Connector.
         *开始处理请求
         * @exception LifecycleException if a fatal startup error occurs
         */
        @Override
        protected void startInternal() throws LifecycleException {
    
            // Validate settings before starting
            if (getPort() < 0) {
                throw new LifecycleException(sm.getString(
                        "coyoteConnector.invalidPort", Integer.valueOf(getPort())));
            }
    
            setState(LifecycleState.STARTING);
    
            try {
                protocolHandler.start();
            } catch (Exception e) {
                String errPrefix = "";
                if(this.service != null) {
                    errPrefix += "service.getName(): "" + this.service.getName() + ""; ";
                }
    
                throw new LifecycleException
                    (errPrefix + " " + sm.getString
                     ("coyoteConnector.protocolHandlerStartFailed"), e);
            }
        }

     protocolHandler.start()

    这里默认调用的是Http11NioProtocol。start()

    先调用构造方法

     public Http11NioProtocol() {
            endpoint=new NioEndpoint();
            cHandler = new Http11ConnectionHandler(this);
            ((NioEndpoint) endpoint).setHandler(cHandler);
            setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
            setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
            setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
        }

     

    AbstractProtocol.start()

    public abstract class AbstractProtocol<S> implements ProtocolHandler,MBeanRegistration

     @Override
        public void start() throws Exception {
            if (getLog().isInfoEnabled())
                getLog().info(sm.getString("abstractProtocolHandler.start",
                        getName()));
            try {
                endpoint.start();
            } catch (Exception ex) {
                getLog().error(sm.getString("abstractProtocolHandler.startError",
                        getName()), ex);
                throw ex;
            }
        }

    endpoint.start()===>调用的是NioEndpoint.startInternal()

    /**
         * Start the NIO endpoint, creating acceptor, poller threads.启动端点,创建接收器,轮询线程
         */
        @Override
        public void startInternal() throws Exception {
    
            if (!running) {
                running = true;
                paused = false;
    
                processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getProcessorCache());
                eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                                socketProperties.getEventCache());
                nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getBufferPool());
    
                // Create worker collection
                if ( getExecutor() == null ) {
                    createExecutor();
                }
    
                initializeConnectionLatch();
    
                // Start poller threads
                pollers = new Poller[getPollerThreadCount()];
                for (int i=0; i<pollers.length; i++) {
                    pollers[i] = new Poller();
                    Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
                    pollerThread.setPriority(threadPriority);
                    pollerThread.setDaemon(true);
                    pollerThread.start();
                }
    
                startAcceptorThreads();
            }
        }

    上面

    1、

    processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
    socketProperties.getProcessorCache());

    设置处理器缓存大小:用SynchronizedStack这种LIFO(后进先出)队列存储。默认大小为128,默认处理器缓存最大限制是500。-1是无限制。

    eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
    socketProperties.getEventCache());

     设置事件缓存大小:默认大小为128,默认事件缓存最大限制是500。-1是无限制。

    nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
    socketProperties.getBufferPool());

    Bytebuffer cache, each channel holds a set of buffers (two, except for SSL holds four)字节缓冲区缓存,每个通道都包含一组缓冲区(两个,SSL除外)

    设置通道缓存大小:默认大小为128,默认通道缓存最大限制是500。-1是无限制。

    2、

    initializeConnectionLatch();初始化LimintLatch   connectionLimitLatch变量。这个变量用来统计endpoint处理的连接数,并限制最大连接数

    通过使用LimintLatch这个类实现限制最大socket连接数

    tomcat默认的最大连接数位10000

    /**
    * Shared latch that allows the latch to be acquired a limited number of times
    * after which all subsequent requests to acquire the latch will be placed in a
    * FIFO queue until one of the shares is returned.
    */
    共享锁存器允许获取有限次数的锁存器,之后,所有后续获取锁存器的请求将被置于FIFO队列中,直到其中一个共享被返回。
     public class LimitLatch 

    3、Start poller threads启动轮询线程。线程数通过Math.min(2,Runtime.getRuntime().availableProcessors());这个方法获取最小的处理器数量,使用min方法找到最小值

    4startAcceptorThreads启动接收器线程。后台线程监听传入的TCP / IP连接,并将其交给适当的处理器。

     这里试着描绘大概流程

      startAcceptorThreads()方法会创建Acceptor线程对象

                  开启线程,循环等待ServerSocket.accept()方法接收到新的连接。然后会将这个socket注册到Poller这个轮询线程。生成一个KeyAttachment对象与socket相关联(后面会用到)

      由第3步已经开启的轮询线程,当这个socket发送请求时,Poller线程就收到连接请求后会将

        调用NioEndpoint.processSocket(KeyAttachment attachment, SocketStatus status, boolean dispatch)方法,这个方法会开启内部类NioEndpoint.SocketProcessor线程的run()方法

       其内部执行调用NioEndpoint.Handler.process(SocketWrapper<NioChannel> socket, SocketStatus status)。---调用的是子类AbstractProtocol.AbstractConnectionHandler.process()

      。。。省略一大堆复杂调用。。。。。

      最后会调用Http11NioProcessor.process(SocketWrapper<S> socketWrapper)方法中调用CoyoteAdapter.service(request, response);将请求传递到context中。

      

      剩余换一章分析。

    到这里tomcat就启动完成了。调用线程等待客户端连接。。。

  • 相关阅读:
    Vue CLI Plugin Electron Builder 打包出现空白问题
    git 不小心提交大文件出错问题
    electron-vue创建项目
    electron ico文件问题
    多尺寸ico图标制作工具GIMP
    ps ico图标制作插件
    fluent-ffmpeg
    CopyWebpackPlugin 拷贝某个文件夹的文件到某个文件夹
    electron-vue 目录有中文打包报错问题
    js 给控件新增class
  • 原文地址:https://www.cnblogs.com/gne-hwz/p/7798021.html
Copyright © 2020-2023  润新知