1. 程式人生 > >server和service的啟動過程

server和service的啟動過程

伺服器與服務
server介面中提供addService(Service service)和removeService(Service service)來新增和刪除服務
server的init方法和start方法會分別迴圈呼叫每個service的init方法和start方法來啟動所有的服務

org.apache.catalina.core.StandardServer    標準的伺服器

Lifecycle-MBeanBase                                   生命週期


server的預設實現類:

org.apache.catalina.core.StandardServer

繼承關係:

public final class StandardServer extends LifecycleMBeanBase implements Server
public abstract class LifecycleMBeanBase extends LifecycleBase implements JmxEnabled
public abstract class LifecycleBase implements Lifecycle
init和start方法就在LifecycleBase裡面,但是LifecycleBase又呼叫了initInternal,startInternal方法
initInternal,startInternal方法都是模板方法,由子類具體實現,所以呼叫StandardServer的init和start方法時
會執行StandardServer自己的initInternal,startInternal方法。這就是Tomcat生命週期的管理方式。

StandardServer自己的initInternal,startInternal方法分別呼叫每個service的start和init方法:

protected void startInternal() throws LifecycleException {
    this.fireLifecycleEvent("configure_start", (Object)null);
    this.setState(LifecycleState.STARTING);
    this.globalNamingResources.start();
    Object var1 = this.servicesLock;
    synchronized(this.servicesLock) {
        for(int i = 0; i < this.services.length; ++i) {
            this.services[i].start();
        }
    }
}
StandardServer還實現了await方法,Catalina中就是呼叫它讓伺服器進入等待狀態的。
該方法的處理邏輯是首先判斷埠號port,然後根據port的值分為三種情況:
port為-2:
    直接退出,不進入迴圈。
port為-1:
    進入一個while(!stopAwait)的迴圈,並且在內部沒有break跳出的語句,stopAwait標誌是有呼叫stop方法才會設定
    為true,所以port為-1時只有在外部呼叫stop方法才會退出迴圈。
port為其他值:
    也會進入一個while(!stopAwait)的迴圈,不過同時會在port所在埠啟動一個ServerSocket來監聽關閉命令,如果接受到了
    則會是用break跳出迴圈。
    這裡的埠port和關閉命令shutdown是在conf/server.xml中配置的,如下:
    <Server port="8005" shutdown="SHUTDOWN">
    這時會在8005埠監聽SHUTDOWN命令,如果接收到了就會關閉tomcat。如果不想是用網路命令來關閉伺服器,可以將埠設定為-1


service的預設實現類:
      org.apache.catalina.core.StandardService

繼承關係:

public class StandardService extends LifecycleMBeanBase implements Service
StandardService也繼承自LifecycleMBeanBase,所以它的init和start方法最終也會呼叫initInternal和startInternal
protected void initInternal() throws LifecycleException {
    super.initInternal();
    if(this.engine != null) {
        this.engine.init();//啟動了
    }

    Executor[] arr$ = this.findExecutors();
    int arr$1 = arr$.length;

    int len$;
    for(len$ = 0; len$ < arr$1; ++len$) {
        Executor i$ = arr$[len$];
        if(i$ instanceof JmxEnabled) {
            ((JmxEnabled)i$).setDomain(this.getDomain());
        }

        i$.init();//啟動了
    }

    this.mapperListener.init();//啟動了
    Object var11 = this.connectorsLock;
    synchronized(this.connectorsLock) {
        Connector[] var12 = this.connectors;
        len$ = var12.length;

        for(int var13 = 0; var13 < len$; ++var13) {
            Connector connector = var12[var13];

            try {
                connector.init();//啟動了
            } catch (Exception var9) {
                String message = sm.getString("standardService.connector.initFailed", new Object[]{connector});
                log.error(message, var9);
                if(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
                    throw new LifecycleException(message);
                }
            }
        }

    }
}
StandardService中的initInternal和startInternal方法主要呼叫了container,executors,mapperListener,connectors的init和start方法。
mapperListener是Mapper的監聽器,可以監聽container容器的變化
executors是用在connectors中管理執行緒的執行緒池,在config/server.xml中如下:
<Service name="Catalina">
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
            maxThreads="150" minSpareThreads="4"/>
    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
</Service>
這樣Connector就配置了一個叫tomcatThreadPoold的執行緒池,最多可以同時啟動150個執行緒,最少要有4個可用執行緒