Tomcat-生命周期管理

看透SpringMVC源代码分析与实践

Lifecycle接口

Tomcat通过org.apache.catalina.Lifecycle接口统一管理生命周期,所有有生命周期的组件都实现了Lifecycle接口。
这里写图片描述
Lifecycle一共做了四件事:

  • 定义了13个String类型常量,用于LifecycleEvent事件的type属性中,作用是区分组件发出的LifecycleEvent事件时的状态(如初始化前,启动前,启动中等)。
  • 定义了三个管理监听器的方法addLifecycleListener,findLifecycleListeners,removeLifecycleListener
  • 定义了四个生命周期方法init,start,stop和destroy
  • 定义了获取当前状态的两个方法getStategetStateName
//org.apache.catalina.Lifecycle
public interface Lifecycle {

    public static final String BEFORE_INIT_EVENT = "before_init";
    public static final String AFTER_INIT_EVENT = "after_init";
    public static final String START_EVENT = "start";
    public static final String BEFORE_START_EVENT = "before_start";
    public static final String AFTER_START_EVENT = "after_start";
    public static final String STOP_EVENT = "stop";
    public static final String BEFORE_STOP_EVENT = "before_stop";
    public static final String AFTER_STOP_EVENT = "after_stop";
    public static final String AFTER_DESTROY_EVENT = "after_destroy";
    public static final String BEFORE_DESTROY_EVENT = "before_destroy";
    public static final String PERIODIC_EVENT = "periodic";
    public static final String CONFIGURE_START_EVENT = "configure_start";
    public static final String CONFIGURE_STOP_EVENT = "configure_stop";

    public void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);

    public void init() throws LifecycleException;
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
    public void destroy() throws LifecycleException;

    public LifecycleState getState();
    public String getStateName();
}

LifecycleBase

Lifecycle的默认实现类是org.apache.catalina.util.LifecycleBase,所有的生命周期组件都直接或者间接的集成了LifecycleBase它为Lifecycle接口提供了默认的实现。

  • 监听器管理是专门使用了一个LifecycleSupport来完成的,LifecycleSupport中定义了一个成员变量LifecycleListener数组,用来保存所有的监听器,没然后定义了添加,查找,删除和执行监听器的方法。
  • 生命周期方法中设置了相应的模板方法,init,start,stop和destroy分别调用了abstract模板方法initInternal,startInternal,stopInternal,destroyInternal
  • 组件当前的生命周期状态,则由一个volatile成员变量LifecycleState保持。

三个管理监听器方法和一个执行监听器方法
监听管理的的添加,查找,删除和执行监听器的方法都是使用了LifecycleSupport来管理的。

//org.apache.catalina.util.LifecycleBase
public abstract class LifecycleBase implements Lifecycle {

    //让LifecycleSupport持有当前对象this
    private LifecycleSupport lifecycle = new LifecycleSupport(this);

    //addLifecycleListener方法交由LifecycleSupport处理。
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
      lifecycle.addLifecycleListener(listener);
    }

    //findLifecycleListeners方法交由LifecycleSupport处理。
    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    //removeLifecycleListener方法交由LifecycleSupport处理。
    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    //fireLifecycleEvent方法交由LifecycleSupport处理。
    protected void fireLifecycleEvent(String type, Object data) {
        lifecycle.fireLifecycleEvent(type, data);
    }

}

LifecycleBase中的addLifecycleListener,findLifecycleListeners,removeLifecycleListener以及fireLifecycleEvent方法分别调用了LifecycleSupport的同名方法,LifecycleSupport 通过一个数组属性listeners来保存

//org.apache.catalina.util.LifecycleSupport 
public final class LifecycleSupport {
    //持有lifecycle的对象
    private Lifecycle lifecycle = null;

    public LifecycleSupport(Lifecycle lifecycle) {
       super();
        this.lifecycle = lifecycle;
    }

    //定义一个成员变量listeners,记录所有的的事件监听
    private LifecycleListener listeners[] = new LifecycleListener[0];

    //当监听发生变化时进行同步的同步锁
    private final Object listenersLock = new Object();

    //将listener添加至listeners[]中
    public void addLifecycleListener(LifecycleListener listener) {
      synchronized (listenersLock) {
         LifecycleListener results[] = new LifecycleListener[listeners.length + 1]; 
            for (int i = 0; i < listeners.length; i++)
                results[i] = listeners[i];
            results[listeners.length] = listener;
            listeners = results;
      }
    }
    //findLifecycleListeners,removeLifecycleListener略....

    //通知所有listeners,触发type类型的事件
    public void fireLifecycleEvent(String type, Object data) {
      LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
      LifecycleListener interested[] = listeners;
      for (int i = 0; i < interested.length; i++)
          interested[i].lifecycleEvent(event);
    }
}

四个生命周期方法
只拿init方法作为示例。

//org.apache.catalina.util.LifecycleBase
public abstract class LifecycleBase implements Lifecycle {
    private volatile LifecycleState state = LifecycleState.NEW;

    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            //init方法调用时,当前状态不是NEW抛出异常
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        /*
         * enum LifecycleState {
         *    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT);
         * }
         * 设置当前状态INITIALIZING,后续触发BEFORE_INIT_EVENT事件
         */
        setStateInternal(LifecycleState.INITIALIZING, null, false);

        //调用模板方法initInternal(),由子类实现
        initInternal();

        /*
         * enum LifecycleState { 
         *   INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT);
         * }
         * 设置当前状态INITIALIZED,后续触发AFTER_INIT_EVENT事件
         */
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    }

    protected abstract void initInternal() throws LifecycleException;


   //省略start,stop,destroy 以及startInternal,stopInternal,destroyInternal


    //设置当前状态,并触发该状态对应的事件
    private synchronized void setStateInternal(LifecycleState state,
            Object data, boolean check) throws LifecycleException {
        //省略日志,check state部分代码....

        this.state = state;

        //触发state对应的事件
        String lifecycleEvent = state.getLifecycleEvent();
        if (lifecycleEvent != null) {
            fireLifecycleEvent(lifecycleEvent, data);
        }
    }
}

获取当前状态

//org.apache.catalina.util.LifecycleBase
public abstract class LifecycleBase implements Lifecycle {
    @Override
    public LifecycleState getState() {
        return state;
    }

    @Override
    public String getStateName() {
        return getState().toString();
    }

}

典型的生命周期组件

TOMCAT启动-源码跟踪中,Bootstrap.load() 的执行过程细节是:Bootstrap.load() --> Catalina.load() --> getServer().init() --> LifecycleBase.init() --> StandardServer.initInternal().start也是类似。

StandardServer
- Catalina在调用init(),start(),stop()方法时,最终都调用的是LifecycleBase的同名方法,而在LifecycleBase内部又是调用的StandardServer的xxxInternal()方法。
- Catalina在调用await()方法时,则调用的是,StandardServer的同名方法

//org.apache.catalina.core.StandardServer
protected void initInternal() throws LifecycleException {
  //JMX 省略....
  //省略其他部分.....
  // Initialize our defined Services
  for (int i = 0; i < services.length; i++) {
       services[i].init();
   }
}

protected void startInternal() throws LifecycleException {
    //省略其他部分.....
   // Start our defined Services
   synchronized (services) {
       for (int i = 0; i < services.length; i++) {
           services[i].start();
       }
   }
}

public void await() {
    //server.xml中<Server port="8005" shutdown="SHUTDOWN">
    //port默认8005,shutdown默认值为SHUTDOWN

    //如果端口是-2,则不进入方法,直接返回。
     if( port == -2 ) {
         return;
     }

    //如果端口是-1则进入循环,但是无法通过网络命令退出
     if( port==-1 ) {
         try {
             awaitThread = Thread.currentThread();
             while(!stopAwait) {
                Thread.sleep( 10000 );
             }
         } finally {
             awaitThread = null;
         }
         return;
     }

    //如果不是-1,-2(应该是一个大于0的端口),则会新建一个监听关闭命令的serverSocket;
     awaitSocket = new ServerSocket(port, 1,InetAddress.getByName(address));

    awaitThread = Thread.currentThread();
    while (!stopAwait) {
        ServerSocket serverSocket = awaitSocket;
        if (serverSocket == null) {
            break;
        }

        //监听关闭连接
        Socket socket = serverSocket.accept();
        StringBuilder command = new StringBuilder();
        InputStream stream =socket.getInputStream();

        //匹配关闭命令是否等于"SHUTDOWN"
        boolean match = command.toString().equals(shutdown);
        if (match) {
            break;
        } 
    }
 }

StandardService
StandardService的默认实现是org.apache.catalina.core.StandardService,在StandardServerinit(),start()方法,会循环调用Service的start(),init()方法,
最终也会经过LifecycleBase最终调用StandardService的initInternal(),startInternal()方法。

 //org.apache.catalina.core.StandardService
 protected void initInternal() throws LifecycleException {

     super.initInternal();

     //初始化container
     if (container != null) {
         container.init();
     }

     //Executors:Connectors线程池
     for (Executor executor : findExecutors()) {
         if (executor instanceof LifecycleMBeanBase) {
             ((LifecycleMBeanBase) executor).setDomain(getDomain());
         }
         executor.init();
     }

     //初始化Connectors
     synchronized (connectors) {
         for (Connector connector : connectors) {
            connector.init();
         }
     }
 }

protected void startInternal() throws LifecycleException {

    setState(LifecycleState.STARTING);

    //首先启动Container 
    if (container != null) {
        synchronized (container) {
            container.start();
        }
    }

    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }

    //其次启动Connectors 
    synchronized (connectors) {
        for (Connector connector: connectors) {
            // If it has already failed, don't try and start it
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}

其中executor配置在Server.xml中,默认是备注释掉,未开启。


<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>

    <Connector executor="tomcatThreadPool"
        port="8080" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443" />
 </Service>
</Server> 

上述配置表示Connector配置一个叫做tomcatThreadPool的线程池,最多可同时启用150个线程,至少要有4个可用线程。

猜你喜欢

转载自blog.csdn.net/it_freshman/article/details/81634824
今日推荐