Tomcat源码学习

来源:互联网 发布:VueJS循环数组取值 编辑:程序博客网 时间:2024/06/05 15:26

之前一直都是只会用tomcat,也只是知道这是个调用各种各样bean的容器,但是却有不少疑问,比如一个http请求如何从客户端到最终处理的servlet手里。今天下了源码来初步学习下,以下为笔记,基于tomcat7.0.4的源码。

当tomcat启动时,调用catalina.bat,然后调用org.apache.catalina.startup.Bootstrap中的main(),再到catalina.java中的load()。

如下是load函数一部分:

Digester digester = createStartDigester();file = configFile();inputStream = new FileInputStream(file);digester.parse(inputSource);//解析conf/server.xml文件getServer().init();

server.xml中,有如下结构:

<Server port="8005" shutdown="SHUTDOWN">  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />                             ..............   <!-- Global JNDI resources       Documentation at /docs/jndi-resources-howto.html  -->  <GlobalNamingResources>    <!-- Editable user database that can also be used by         UserDatabaseRealm to authenticate users    -->    <Resource name="UserDatabase" auth="Container"              type="org.apache.catalina.UserDatabase"              description="User database that can be updated and saved"              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"              pathname="conf/tomcat-users.xml" />  </GlobalNamingResources>  <Service name="Catalina">    <!--The connectors can use a shared executor, you can define one or more named thread pools-->    <!--    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"        maxThreads="150" minSpareThreads="4"/>    -->    <Connector port="8080" protocol="HTTP/1.1"               connectionTimeout="20000"               redirectPort="8443" />                        ................     <!-- Define an AJP 1.3 Connector on port 8009 -->    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />    <!-- You should set jvmRoute to support load-balancing via AJP ie :    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">    -->  </Service></Server>

createStartDigester()中初始化了StandardServer/StandardService/StandardThreadExecutor/Connector等对象。

protected Digester createStartDigester() {                     .........        // Configure the actions we will be using        digester.addObjectCreate("Server",                                 "org.apache.catalina.core.StandardServer",                                 "className");        digester.addSetProperties("Server");        digester.addSetNext("Server",                            "setServer",                            "org.apache.catalina.Server");                      ........         }

当Server起来后,StandardService就会被start,如下:

protected void startInternal() throws LifecycleException {        // Start our defined Container first        if (container != null) {            synchronized (container) {                container.start();            }        }        synchronized (executors) {            for (Executor executor: executors) {                executor.start();            }        }        // Start our defined Connectors second        synchronized (connectors) {            for (Connector connector: connectors) {                try {                    // If it has already failed, don't try and start it                    if (connector.getState() != LifecycleState.FAILED) {                        connector.start();                    }                } catch (Exception e) {                    log.error(sm.getString(                            "standardService.connector.startFailed",                            connector), e);                }            }        }    }

Service会启动它的连接器和容器,一个Service包含一个容器和多个连接器。

由于server.xml中定义的协议不同,连接器一般用Http11Protocol或者AjpProtocol

Http11Protocol的构造函数中

public Http11Protocol() {        endpoint = new JIoEndpoint();//初始化JIoEndpoint        cHandler = new Http11ConnectionHandler(this);//指定处理每个请求的Handler        ((JIoEndpoint) endpoint).setHandler(cHandler);    }

会遇到JIoEndpoint这个东西,这是个处理socket请求的类。在他的类的注释中

This class implement a simple server model: one listener thread accepts on a socket and creates a new worker thread for each incoming connection.

说明了他的作用是接受客户端请求并且为每个请求单独建立新的线程来处理。

其中包含了三个子类:SocketProcessor(实际处理每个请求)、Acceptor(分发每个请求)、AsyncTimeout(看起来是超时机制)

我们来看下JIoEndpoint.startInternal()函数:

createExecutor();//建立一个线程池,可以定义最大并发数量startAcceptorThreads();//建立一个监听线程,具体线程类为Acceptorbind。。。。listen。。。

当用户发起请求后,Acceptor中的processSocket()会处理这个请求,调用线程池中的空闲资源:getExecutor().execute(new SocketProcessor(wrapper)); 由Http11Connector的构造函数中可以看到,具体的请求handler是Http11ConnectionHandler类。

鉴于后面都是按照debug的断点一步步的跟踪了,所以就不写了,总之最后就是会new到具体的cmdServlet对象并调用到具体的处理http请求的servlet。

0 0