Tomcat分析(1)结构和启动

1.tomcat顶层结构和启动过程

1.结构
Tomcat顶层容器是Server,代表整个服务器,包含至少一个(或多个)Service.
Service包含至少一个(或多个)Connector 和一个Container.
Connector 负责连接如http连接和https连接,并提供Socket,response,request转换.
Container 封装和管理Servlet及request请求.

Catalina是Tomcat的管理类包含load(含init()),start,stop三个方法.
Catalina调用Server中的start,Server中start的调用包含Service的start,Service的start调用包含Connector 和Container的start.同理stop,load.await方法很重要,此方法直接调用 了Server的await方法,这个方法的作用是进入一个循环,让主线程不会退出。

2.Bootstrap启动
Tomcat的入口是Bootstrap的main,main中通过反射调用Catalina的setAwait(true),load(args)和start().
下面代码都是简写

public static void main(String []args){

if(deamon == null)
Bootstrap bs = new Bootstrap();
bs .init();
deamon =bs;
String command = "start";
if(args.length>0)
command = args[args.length-1];
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();
        } 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) {
        if (t instanceof InvocationTargetException &&
                t.getCause() != null) {
            t = t.getCause();
        }
        handleThrowable(t);
        t.printStackTrace();
System.exit(1);
    }

}
}
public void start(){
if(catalinaDeamon==null)  init();
Method method = catalinaDeamon.getClass().getMothod("start",(Class [])null);
method .invoke(catalinaDeamon,(Object [] )null);

}

3.Catalina启动
setAwait(true)判断Server启动后是否进入等待状态,load(args)加载配置文件和start()启动Server.

public void load(){  getServer().init() }

public void setAwait(boolean b){ await = b; }

public void start(){
if(getServer() == null)  load();
getServer().start();
....
if(await)
await();
stop(;)
}

4.Server启动
Server中提供addServer(),removeServer()来添加删除.
init(),start()循环调用Service中的init(),start().
Server默认实现org.apache.catalina.core.StandarServer,StandarServer继承LifecycleMBeanBase,
LifecycleMBeanBase又继承LifecycleBase,init()和start()定义在LifecycleBase中,LifecycleBase里的init()和start()调用initInternal()和startInernal().这两个都是模板方法,又子类实现

protected void startInternal() throws LifecycleException {
    ……
    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            services[i].start();
        }
    }
}
protected void initInternal() throws LifecycleException {
    ……
    for (int i = 0; i < services.length; i++) {
        services[i].init();
    }
}

StandardServer中还实现了await方法,Catalina中就是调用它让服务器进入等待状态的,其核心代码如下:

public void await() {
    // 如果端口为-2则不进入循环,直接返回
    if( port == -2 ) {
        return;
    }
    // 如果端口为-1则进入循环,而且无法通过网络退出
    if( port==-1 ) {
        try {
            awaitThread = Thread.currentThread();
            while(!stopAwait) {
                try {
                    Thread.sleep( 10000 );
                } catch( InterruptedException ex) {
                    // continue and check the flag
                }
            }
        } finally {
            awaitThread = null;
        }
        return;
    }
      // 如果端口不是-1和-2(应该大于0),则会新建一个监听关闭命令的
 ServerSocket awaitSocket = new ServerSocket(port, 1,InetAddress.getByName(address));
 while (!stopAwait) {
ServerSocket serverSocket = awaitSocket;
    if (serverSocket == null) {
        break;
    }


    Socket socket = null;
    StringBuilder command = new StringBuilder();
    InputStream stream;
    socket = serverSocket.accept();
    socket.setSoTimeout(10 * 1000); 
    stream = socket.getInputStream();


    // 检查在指定端口接收到的命令是否和shutdown命令相匹配
boolean match = command.toString().equals(shutdown); 
    // 如果匹配则跳出循环
    if (match) {
        break;
    }
}

5.Service启动
Service的默认实现是org.apache.catalina.core.StandardService,StandardService也继承自LifecycleMBeanBase类,所以init和start方法最终也会调用initInternal和startInternal方法。

protected void initInternal() throws LifecycleException {
    super.initInternal();
    if (container != null) {
        container.init();
    }
    for (Executor executor : findExecutors()) {
        if (executor instanceof JmxEnabled) {
            ((JmxEnabled) executor).setDomain(getDomain());
        }
        executor.init();
    }
    mapperListener.init();
synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            connector.init();
        }
    }
}


protected void startInternal() throws LifecycleException {
    setState(LifecycleState.STARTING);
    if (container != null) {
        synchronized (container) {
            container.start();
        }
}
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }
    mapperListener.start();
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
}
        }
    }
}

可以看到,StandardService中的initInternal和startInternal方法主要调用container、executors、mapperListener、connectors的init和start方法。mapperListener是Mapper的监听器,可以监听container容器的变化,executors是用在connectors中管理线程的线程池。
serverx.xml配置文件中配置了一个叫tomcatThreadPool的线程池。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值