Tomcat分析(1)结构和启动

来源:互联网 发布:利用淘宝客刷单 编辑:程序博客网 时间:2024/06/15 12:34

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的线程池。