`
茴香豆
  • 浏览: 132246 次
  • 性别: Icon_minigender_2
  • 来自: 桂林
社区版块
存档分类
最新评论
阅读更多

     Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的组件是Catalina Servlet容器,其它的组件按照一定的格式要求配置在这个容器中

    Tomcat各组件是在<Tomcat_HOME>\conf\server.xml文件中配置,其配置文件内容如下

   

<Server port="8005" shutdown="SHUTDOWN">

    <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"/>
    -->
    
    
    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" />
    -->           
    <!-- Define a SSL HTTP/1.1 Connector on port 8443
         This connector uses the JSSE configuration, when using APR, the 
         connector should be using the OpenSSL style configuration
         described in the APR documentation -->
    <!--
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">         
    --> 
    <Engine defaultHost="localhost" name="Catalina">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->        

      <!-- The request dumper valve dumps useful debugging information about
           the request and response data received and sent by Tomcat.
           Documentation at: /docs/config/valve.html -->
      <!--
      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
      -->

      <!-- This Realm uses the UserDatabase configured in the global JNDI
           resources under the key "UserDatabase".  Any edits
           that are performed against this UserDatabase are immediately
           available for use by the Realm.  -->
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

      <!-- Define the default virtual host
           Note: XML Schema validation will not work with Xerces 2.2.
       -->
      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"  
               prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
        -->

      <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>
    </Engine>
  </Service>
</Server>

   server.xm文件的基本结构如下:

  

       <Server> 代表了整个Catalina Servlet 容器,它是Tomcat实例的顶层元素。可包含一个或多个<Service>元素

       <Service>包含一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享同一个<Engine>元素

       <Connector>代表和客户程序实际交互的组件,它负责接收客户请求,以及返回客户响应结果。

        <Engine>每个<Service>元素只能包含一个<Engine>元素.  <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.

        <Host>一个<Engine>元素中可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.

        <Contex>每个<Context>元素代表了运行虚拟主机上的但个Web应用.一个<Host>元素中可以包含多个<Context>元素.
        组件的关系图如下

            

 

 下面,介绍Tomcat的基本元素

 1.配置Server元素

    Server>元素代表了整个Catalina  Servler容器,它是Tomcat实例的顶层元素,由org.apache.catalina.Server接口来定义.<Server>元素中可以包含一个或者多个<Service>元素,但<Server>元素不能作为任何其他元素的子元素.

  

<Server port="8005" shutdown="SHUTDOWN">

    className    :指定实现org.apache.catalina.Server接口的类,默认值为org.apache.catalina.core.StandardServer.
       port              :指定Tomcat服务器监听shutdown命令的端口.终止Tomcat服务运行时,必须在Tomcat服务器所在的机器上发出Shutdown命令.该属性是必须设定的.
       shutdown      :指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性是必须设定的.

  2.配置Service元素

    <Service>元素由org.apache.catalina.Service接口定义,它把韩一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享一个<Engine>元素.  

   

<Service name="Catalina">

   <Service>处理所有直接由Tomcat服务器接收的Web客户请求。

  className    :指定实现org.apache.catalina.Service接口的类,默认值org.apache.catalina.core.StandardService.
    name              :定义Service的名字.

 3.配置Engine元素

    <Engine>元素由org.apahe.catalina.Engine接口定义.  每个<Service>元素只能包括一个<Engine>元素.  <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.

  

<Engine defaultHost="localhost" name="Catalina">

 className    :指定实现org.apache.catalina.Engine接口的类,默认值为org.apache.catalina.core.StandardEngine.
       name              :定义Engine的名字.
在<Engine>元素中可以包含如下的子元素:
               <Logger>
               <Realm>
               <Valve>
               <Host>
4.配置Connector元素

  <Connector>元素由org.apache.catalina.Connector接口定义.<Connector>元素代表与客户程序实际交互的组件,它负责接收客户的请求,以及向客户返回响应结果。

 

 <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

  

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>

  第一个<Connector>元素定义了一个HTTP  Connector,它通过8080端口接收HTTP请求;
   第二个<Connector>元素定义了一个JK  Connector,它通过8009端口接收由其他HTTP服务器(如Apache服务器)转发过来的客户请求.
   <Connector>属性含义(共同属性):

--------------------------------------------------------------
       className            :指定实现org.apache.catalina.Connector  接口的类,默认值为org.apache.catalina.core.StandardConnector.
       enableLookups    :如果设为true,表示支持域名解析,可以把IP地址解析为主机名.Web应用调用request.getRemostHost方法将返回客户的主机名.该属性默认值为true.
       redirectPort      :指定转发端口.如果当前端口只支持non-SSL请求,在需要安全通信的场合,将把客户请求转发到基于SSL的redirectPort的端口.
 HttpConnector的属性描述如下:
--------------------------------------------------------------
       calssName            :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomcat5.CoyoteConnector.
       enableLookups    :同上.
       redirectPort      :同上.
       prot                      :设定TCP/IP断口号,默认为8080.
       address                :如果服务器有两个以上IP地址,该属性可以设定端口监听的IP地址,默认情况下,端口会监听服务器上所有IP地址.
       bufferSize          :设定由端口创建的输入流的缓存大小,默认值为2048byte.
       protocol              :设定HTTP协议,默认值为HTTP/1.1.
       maxThreads          :设定处理客户请求的线程的最大数目,这个值也决定了服务器可以同时响应客户请求的最大数目,默认值为200.
       acceptCount        :设定在监听端口队列中的最大客户请求数,默认值为10.  如果队列已满,客户请求将被拒绝.
       connectionTimeout  :定义建立客户连接超时的时间,以毫秒为单位.如果设置为-1,表示不限制建立客户连接的时间.

       JK  Connector  的属性如下:
--------------------------------------------------------------
       className            :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomact5.CoyoteCnnector.
       enableLookups    :同上.
       redirectPort      :同上.
       port                      :设定AJP端口号.
       protocol              :必须设定为AJP/1.3协议.

5.配置<Host>元素

  <Host>元素由org.apache.catalina.Host接口定义.一个<Engine>元素可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.  

 

 <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">

  以上代码定义了一个名为localhost的虚拟主机,Web客户访问它的URL为:  http://localhost:8080/
  className        :指定实现org.apache.catalina.Host接口的类,默认值为org.apache.catalina.core.StandardHost.
       appBase            :指定虚拟主机的目录,可以指定绝对目录,也可以指定相对于<CATALINA_HOME>的相对目录.  如果此项没有设定,默认值为<CATALINA_HOME>/webapps.
       unpackWARs      :如果此项设为true,表示将把Web应用的WAR文件先展开为开放目录结构后再运行.如果设为false,将直接运行WAR文件.
       autoDeploy      :如果此项设为true,表示当Tomcat服务器处于运行状态时,能够监测appBase下的文件,如果有新的Web应用加入进来,会自动发布这个Web应用.
       alias                :指定虚拟主机的别名,可以指定多个别名.
       deployOnStartup  :如果此项设为true,表示Tomcat服务器启动时会自动发布appBase目录下的所有Web应用,如果Web应用在server.xml中没有相应的<Context>元素,将采用Tomcat默认的Context.  deployOnStartup的默认值为true.
       name                  :定义虚拟主机的名字.}
 在<Host>元素中可以包含如下的子元素:
               <Logger>
               <Realm>
               <Valve>
               <Context>
6.配置Contex元素

   <Context>元素由org.apache.catalina.Context接口定义.  <Context>元素是使用最频繁的元素.  每个<Context>元素代表了运行在虚拟主机上的单个Web应用.  一个<Host>元素中可以包含多个<Context>元素.

  

 <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>

  
className      :指定实现org.apache.catalina.Context接口的类,默认值为org.apache.catalina.core.StandardContext.
       path                :指定访问该Web应用的URL入口.
       docBase          :指定Web应用的文件路径.可以给定绝对路径,也可以给定相对于Host的appBase属性的相对路径.  如果Web应用采用开放目录结构,那就指定Web应用的根目录;如果Web应用是个WAR文件,那就指定WAR文件的路径.
       reloadable    :如果这个属性设为true,Tomcat服务器在运行状态下会监视在WEB-INF/class和WEB-INF/lib目录下CLASS文件的改动.如果检测到有calss文件被更新,服务器会自动重新加载Web应用.
       cookies          :指定是否通过Cookie来支持Session,默认为true.
       useNaming      :指定是否支持JNDI,默认为true.

<----------------------------------------------------------------------------------------------------------------------------->

 

下面解说下tomcat的启动过程

 从开始学习网页编程时,我就一直在疑惑,为什么这个程序不要main函数,直接启动服务器就行了。但是服务器又是怎么启动的?

 最近看了一片文档,以及自己查看tomcat源码,才大概了解那么一点。

 1.启动tomcat

    apache-tomcat-6.0.29\bin\bootstrap.jar
    org.apache.catalina.startup.Bootstrap  start 
   Bootstrap
Tomcat的入口。比如启动、关闭、重启都是通过这个类实现对tomcat的控制。
2.ClassLoader的使用
Tomcat
对不同的模块可能使用不同的ClassLoader加载。这也就是为什么很多类不在启动的classpath中,却可以被它调用的原因。
下面是Bootstrap初始化ClassLoader的方法:

 

  private void initClassLoaders() {
        try {
            commonLoader = createClassLoader("common", null);
            if( commonLoader == null ) {
                // no config file, default to this loader - we might be in a 'single' env.
                commonLoader=this.getClass().getClassLoader();
            }
            catalinaLoader = createClassLoader("server", commonLoader);
            sharedLoader = createClassLoader("shared", commonLoader);
        } catch (Throwable t) {
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

 

 

 

 


   下图是Tomcat用户手册上看到的。
       Bootstrap
          |
       System
          |
       Common
      /      \
 Catalina   Shared
 (server)     /   \
      Webapp1  Webapp2 ...  
Bootstrap
JVM提供的
System
是在classpath中提供的
Common
包含配置文件/org/apache/catalina/startup/catalina.properties中指定的类库支持
Catalina
Shared都从Common中继承,包含的类库也在上面配置文件中指定。
WebappX
在部署单个Tomcat5实例时指定。一个webapp下面的类库对另外一个是不可见的
Tomcat
加载类的顺序和普通的不太一样,如下:
Bootstrap classes of your JVM
System class loader classses (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/common/classes
$CATALINA_HOME/common/endorsed/*.jar
$CATALINA_HOME/common/lib/*.jar
$CATALINA_BASE/shared/classes
$CATALINA_BASE/shared/lib/*.jar
注意,如果希望不使用JVM本身提供的类。这时可以使用jdkendorsed 特性

   3. Catalina类的作用

    如果要启动Tomcat,那么一个org.apache.catalina.startup.Catalina实例就生成,由它完成接下来的工作。

   下面是它启动的代码

 public void start() {

        if (getServer() == null) {
            load();
        }

        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();
        
        // Start the new server
        if (getServer() instanceof Lifecycle) {
            try {
                ((Lifecycle) getServer()).start();
            } catch (LifecycleException e) {
                log.error("Catalina.start: ", e);
            }
        }

        long t2 = System.nanoTime();
        if(log.isInfoEnabled())
            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");

        try {
            // Register shutdown hook
            if (useShutdownHook) {
                if (shutdownHook == null) {
                    shutdownHook = new CatalinaShutdownHook();
                }
                Runtime.getRuntime().addShutdownHook(shutdownHook);
                
                // If JULI is being used, disable JULI's shutdown hook since
                // shutdown hooks run in parallel and log messages may be lost
                // if JULI's hook completes before the CatalinaShutdownHook()
                LogManager logManager = LogManager.getLogManager();
                if (logManager instanceof ClassLoaderLogManager) {
                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                            false);
                }
            }
        } catch (Throwable t) {
            // This will fail on JDK 1.2. Ignoring, as Tomcat can run
            // fine without the shutdown hook.
        }

        if (await) {
            await();
            stop();
        }

    }

 

 

  启动过程先载入配置文件,然后根据配置文件启动的Server实例启动实例 

 

 

 

 

 

 

  4. Server对象的生成

    服务的生成就是根据配置文件server.xml,实例化的对象。对象实例化过程中,会做载入webapp,在特定端口等待客户连接等工作。
server.xml到对象的映射是通过commons-digester.jar包完成的。这个包的一个主要功能就是映射xmljava对象。
catalina
类的方法createStartDigester完成了这个工作。部分代码如下

 

 protected Digester createStartDigester() {
        long t1=System.currentTimeMillis();
        // Initialize the digester
        Digester digester = new Digester();
        digester.setValidating(false);
        digester.setRulesValidation(true);

     -------------  -------------   -------------
 digester.addObjectCreate("Server",
                                 "org.apache.catalina.core.StandardServer",
                                 "className");
        digester.addSetProperties("Server");
        digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");
  ————————————————————————————
     // Add RuleSets for nested elements
        digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
        digester.addRuleSet(new EngineRuleSet("Server/Service/"));
        digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
        digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
        digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
        digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Cont


——————————————————
return (digester);
}


     digester会在解析之后,返回一个对象。

  5. 服务的中止
org.apache.catalina.core.StandardServer.await
是保持tomcat运行的秘密。方法启动一个ServerSocket,侦听发出停止的字符串。这是一个死循环。当有停止运行的字符发出,跳出此循环。 

     

 public void await() {
        // Negative values - don't wait on port - tomcat is embedded or we just don't like ports
        if( port == -2 ) {
            // undocumented yet - for embedding apps that are around, alive.
            return;
        }
        if( port==-1 ) {
            while( true ) {
                try {
                    Thread.sleep( 10000 );
                } catch( InterruptedException ex ) {
                }
                if( stopAwait ) return;
            }
        }
        
        // Set up a server socket to wait on
        ServerSocket serverSocket = null;
        try {
            serverSocket =
                new ServerSocket(port, 1,
                                 InetAddress.getByName("localhost"));
        } catch (IOException e) {
            log.error("StandardServer.await: create[" + port
                               + "]: ", e);
            System.exit(1);
        }

        // Loop waiting for a connection and a valid command
        while (true) {

            // Wait for the next connection
            Socket socket = null;
            InputStream stream = null;
            try {
                socket = serverSocket.accept();
                socket.setSoTimeout(10 * 1000);  // Ten seconds
                stream = socket.getInputStream();
            } catch (AccessControlException ace) {
                log.warn("StandardServer.accept security exception: "
                                   + ace.getMessage(), ace);
                continue;
            } catch (IOException e) {
                log.error("StandardServer.await: accept: ", e);
                System.exit(1);
            }

            // Read a set of characters from the socket
            StringBuffer command = new StringBuffer();
            int expected = 1024; // Cut off to avoid DoS attack
            while (expected < shutdown.length()) {
                if (random == null)
                    random = new Random();
                expected += (random.nextInt() % 1024);
            }
            while (expected > 0) {
                int ch = -1;
                try {
                    ch = stream.read();
                } catch (IOException e) {
                    log.warn("StandardServer.await: read: ", e);
                    ch = -1;
                }
                if (ch < 32)  // Control character or EOF terminates loop
                    break;
                command.append((char) ch);
                expected--;
            }

            // Close the socket now that we are done with it
            try {
                socket.close();
            } catch (IOException e) {
                ;
            }

            // Match against our command string
            boolean match = command.toString().equals(shutdown);
            if (match) {
                break;
            } else
                log.warn("StandardServer.await: Invalid command '" +
                                   command.toString() + "' received");

        }

        // Close the server socket and return
        try {
            serverSocket.close();
        } catch (IOException e) {
            ;
        }

    }

  跳出循环后,系统执行关闭连接等资源的操作,服务就中止了。

Catalina.stopServer方法用于发出一个让服务停止的指令

 Socket socket = new Socket(hostAddress, getServer().getPort());
                OutputStream stream = socket.getOutputStream();
                String shutdown = getServer().getShutdown();
                for (int i = 0; i < shutdown.length(); i++)
                    stream.write(shutdown.charAt(i));
                stream.flush();
                stream.close();
                socket.close();

 

 

 

  • 大小: 59.8 KB
  • 大小: 41.8 KB
分享到:
评论

相关推荐

    tomcat 架构 分析

    在深入分析Tomcat的架构之前,需要了解Tomcat是Apache Jakarta项目中的一个核心项目,是一个免费的开源Servlet容器。它主要用于作为独立服务器或集成到Web服务器中,如Apache和IIS等。作为Web服务器,Tomcat负责解析...

    tomcat6源码分析

    1. 初始化:Tomcat启动时,会读取配置文件server.xml,解析配置信息,构建出服务器的结构。 2. 加载Web应用:根据context.xml配置加载Web应用,创建对应的Context对象。 3. 初始化Servlet:调用Servlet的init()方法...

    tomcat 学习与分析总结资料

    3. **Server结构分析** 在Tomcat的配置文件`server.xml`中,`Server`元素是最顶级的容器,包含多个`Service`,每个`Service`又包含至少一个`Connector`(用于接收和发送HTTP请求)和一个`Engine`(负责处理请求)。...

    tomcat架构的源码分析

    ### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...

Global site tag (gtag.js) - Google Analytics