前言

Tomcat作为Java开发者接触过最重要的web容器,在启动和解决申请过程中做了海量的事件,高级开发者很少关怀,应用SpringMvc之类下层框架一带而过,然而这些局部是Java和网络集大成之作,笔者要带着大家走一遍一次申请,加深tomcat的认知。最好先调试好Tomcat源码

Tomcat基础架构

BootStrap和Catalina

BootStrap

BootStrap就是Tomcat的main函数所在位置,在应用过程中执行脚本catlina.sh或者bat文件即可执行java命令并调用BootStrap的main函数实现tomcat的启动

 public static void main(String args[]) { if (daemon == null) {                // Don't set daemon until init() has completed                Bootstrap bootstrap = new Bootstrap();                try {                    bootstrap.init();                } catch (Throwable t) {                    handleThrowable(t);                    t.printStackTrace();                    return;                }                daemon = bootstrap;            } else {                // When running as a service the call to stop will be on a new                // thread so make sure the correct class loader is used to                // prevent a range of class not found exceptions.                Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);            }......}

Catalina

BootStrap是服务器的入口, 会通过start、stop、stopServer、stopServer等反射调用Catalina的对应办法

public void stopServer() throws Exception {        Method method =            catalinaDaemon.getClass().getMethod("stopServer", (Class []) null);        method.invoke(catalinaDaemon, (Object []) null);    }

Tomcat的外围配置文件server.xml

先来看一下tomcat的容器构造


tomcat容器有多层,Server、service、Engine、Host、Context等,图中有省略
比方一个名称为mytomcat的web我的项目,对应到Container局部,Context名称就是mytomcat
再看一下Tomcat的配置文件server.xml

<Server port="8005" shutdown="SHUTDOWN">    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />    <Listener SSLEngine="on"        className="org.apache.catalina.core.AprLifecycleListener" />    <Listener className="org.apache.catalina.core.JasperListener" />    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />    <GlobalNamingResources>        <Resource auth="Container" description="User database that can be updated and saved"            factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase"            pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase" />    </GlobalNamingResources>    <Service name="Catalina">        <Connector URIEncoding="UTF-8" connectionTimeout="20000"            port="80" protocol="HTTP/1.1" redirectPort="8443" />        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />        <Engine defaultHost="localhost" name="Catalina">            <Realm className="org.apache.catalina.realm.LockOutRealm">                <Realm className="org.apache.catalina.realm.UserDatabaseRealm"                    resourceName="UserDatabase" />            </Realm>            <Host appBase="webapps" autoDeploy="true" name="localhost"                unpackWARs="true">                <Valve className="org.apache.catalina.valves.AccessLogValve"                    directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log."                    suffix=".txt" />            </Host>        </Engine>    </Service>

在启动tomcat的时候,catalina的load办法,会读取server.xml文件的内容,通过Digester组件把server.xml解析成Server对象,并且把Server变成Catalina的成员变量。

咱们看一下catalina的load办法中digester.parse()办法执行后的容器代码构造


这样的话,Tomcat的容器的层级构造就建设起来了。

网络解决局部

Connector

tomcat能够解决多种协定,对立应用Connector组件来实现,在tomcat中一个Service能够对应多个Connector

ProtocolHandler

connector中有个很重要的成员变量protocolHandler, 用来实现多种协定的解析,
比方http协定。基于tcp做集群的AJP协定

Endpoint

AbstractEndpoint是Tcp的解决入口,并且持有Executor;Connector的executor和ProtocolHandler的线程池都是应用这个executor
当有网络工作到来的时候,tomcat会应用这个线程池来解决socket事件

Acceptor 和 Poller

Acceptor是封装新连贯的工作,Endpoint应用独自的线程保护 Poller 是java NIO中Selector的封装,当新连贯到来时唤醒Acceptor线程注册pollerEvent事件来监听连贯

Poller的实现是java的Selector