<!-- Example Server Configuration File -->
<!-- Tomcat服務器配置示例文件 -->

<!-- Note that component elements are nested corresponding to their
     parent-child relationships with each other -->
<!-- 注意,這些組件的構成是根據相互之間的父子關系進行嵌套的。-->

<!-- A "Server" is a singleton element that represents the entire JVM,
     which may contain one or more "Service" instances. The Server
     listens for a shutdown command on the indicated port.

     Note: A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" or "Loggers" at this level.
 -->
<!-- 一個“Server”是一個提供完整的JVM的獨立組件,它可以包含一個或多個
     “Service”實例。服務器在指定的端口上監聽shutdown命令。
     
     注意:一個“Server”自身不是一個“Container”(容器),因此在這里你
     不可以定義諸如“Valves”或者“Loggers”子組件
-->

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


  <!-- Comment these entries out to disable JMX MBeans support -->
  <!-- 這些指令組件關閉JMX MBeans支持 -->
 
  <!-- You may also configure custom components (e.g. Valves/Realms) by
       including your own mbean-descriptor file(s), and setting the
       "descriptors" attribute to point to a ';' seperated list of paths
       (in the ClassLoader sense) of files to add to the default list.
       e.g. descriptors="/com/myfirm/mypackage/mbean-descriptor.xml"
  -->
  <!-- 你也可以通過包含你自己的mbean描述文件配置自定義的組件,然后設置
       “descriptors”屬性為以“;”為分隔的文件名列表嚴將它添加到默認列表
       中,例如:descriptors="/com/myfirm/mypackage/mbean-descriptor.xml"。
 -->
       
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"
            debug="0"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"
            debug="0"/>

  <!-- Global JNDI resources -->
  <!-- 全局JNDI資源 -->
  <GlobalNamingResources>

    <!-- Test entry for demonstration purposes -->
    <!-- 出于示例目的的測試入口 -->
    <Environment name="simpleValue" type="java.lang.Integer" value="30"/>

    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users -->
    <!-- 可編輯的,用來通過UserDatabaseRealm認證用戶的用戶數據庫 -->
    
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
       description="User database that can be updated and saved">
    </Resource>
    <ResourceParams name="UserDatabase">
      <parameter>
        <name>factory</name>
        <value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
      </parameter>
      <parameter>
        <name>pathname</name>
        <value>conf/tomcat-users.xml</value>
      </parameter>
    </ResourceParams>

  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" (and therefore the web applications visible
       within that Container). Normally, that Container is an "Engine",
       but this is not required.

       Note: A "Service" is not itself a "Container", so you may not
       define subcomponents such as "Valves" or "Loggers" at this level.
   -->
  <!-- 一個“Service”是一個或多個共用一個單獨“Container”(容器)的“Connectors”
       組合(因此,應用程序在容器中可見)。通常,這個容器是一個“Engine”
       (引擎),但這不是必須的。
       
       注意:一個“Service”自身不是一個容器,因此,在這個級別上你不可定義
       諸如“Valves”或“Loggers”子組件。
  -->

  <!-- Define the Tomcat Stand-Alone Service -->
  <!-- 定義Tomcat的標準獨立服務 -->
  <Service name="Catalina">

    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Each Connector passes requests on to the
         associated "Container" (normally an Engine) for processing.

         By default, a non-SSL HTTP/1.1 Connector is established on port 8080.
         You can also enable an SSL HTTP/1.1 Connector on port 8443 by
         following the instructions below and uncommenting the second Connector
         entry. SSL support requires the following steps (see the SSL Config
         HOWTO in the Tomcat 5 documentation bundle for more detailed
         instructions):
         * If your JDK version 1.3 or prior, download and install JSSE 1.0.2 or
           later, and put the JAR files into "$JAVA_HOME/jre/lib/ext".
         * Execute:
             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA (Windows)
             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA (Unix)
           with a password value of "changeit" for both the certificate and
           the keystore itself.

         By default, DNS lookups are enabled when a web application calls
         request.getRemoteHost(). This can have an adverse impact on
         performance, so you can disable it by setting the
         "enableLookups" attribute to "false". When DNS lookups are disabled,
         request.getRemoteHost() will return the String version of the
         IP address of the remote client.
    -->
    <!-- 一個“Connector”(連接器)代表一個請求被接收和應答所需要的端點。每個連
         接器通過相關的“Container”(容器)處理請求。
         
         默認情況下,一個非SSL的HTTP/1.1的連接器被綁定在端口8080。你也可以通過
         根據后面的使用說明并取消第二個連接器入口的注釋,在端口8443上建立一個
         SSL HTTP/1.1的連接器。開放SSL支持需要下面幾步(參見Tomcat 5文檔中怎樣
         配置SSL的說明以取得更多的詳細信息):
         * 如果你的JDK是1.3或1.3以前的版本,下載安裝JSSE 1.0.2或以后版本,并放
           置JAR文件到“$JAVA_HOME/jre/lib/ext”目錄下。
         * 帶一個“changeit”的口令值執行:
             %JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA (Windows)
             $JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA (UNIX)
           來生成它自己的證書私鑰。
           
         默認情況下,當一個web應用程序調用請求時,DNS查詢是可行的。這將對性能造
         成一些不利的影響,因此,你可以將“enableLookups”設置為“false”來關閉DNS
         查詢。當DNS查詢被關閉時,request.getRemoteHost()將返回包含遠程客戶IP地
         址的字符串。
  -->

    <!-- Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 -->
    <!-- 在8080端口上定義一個非SSL的HTTP/1.1連接器 -->
    <Connector port="8080"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               debug="0" connectionTimeout="20000"
               disableUploadTimeout="true" />
    <!-- Note : To disable connection timeouts, set connectionTimeout value
     to 0 -->
    <!-- 注意,要關閉連接超時,將connectionTimeout設置為0 -->

<!-- Note : To use gzip compression you could set the following properties :

compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml"
-->
<!-- 注意:要使用gzip壓縮需要設置如下屬性:

compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla,traviata"
compressableMimeType="text/html,text/xml"
-->

    <!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
    <!-- 在端口8443上定義一個SSL的HTTP/1.1的連接器 -->
    <!--
    <Connector port="8443"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" debug="0" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->
    <!-- 在端口8009上定義一個Coyote/JK2 AJP 1.3連接器 -->
    <Connector port="8009"
               enableLookups="false" redirectPort="8443" debug="0"
               protocol="AJP/1.3" />

    <!-- Define a Proxied HTTP/1.1 Connector on port 8082 -->
    <!-- 在8082端口上定義一個代理HTTP/1.1連接器 -->
    <!-- See proxy documentation for more information about using this. -->
    <!-- 參見代理文檔以取得這里使用屬性的更多的信息。 -->
    <!--
    <Connector port="8082"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false"
               acceptCount="100" debug="0" connectionTimeout="20000"
               proxyPort="80" disableUploadTimeout="true" />
    -->

    <!-- 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). -->
    <!-- 一個“Engine”(引擎)代表處理每個請求的入口點(在Catalina內)。這個Tomcat
         的標準獨立引擎實現分析包含在請求中的HTTP頭信息,并將請求傳送到適當的主機
         或虛擬主機上。-->

    <!-- You should set jvmRoute to support load-balancing via JK/JK2 ie :
    <Engine name="Standalone" defaultHost="localhost" debug="0" jvmRoute="jvm1">
    -->
    <!-- 你應該這樣設置jvmRoute以便在JK/JK2通道上支持負載平衡:
    <Engine name="Standalone" defaultHost="localhost" debug="0" jvmRoute="jvm1">
    -->
         
    <!-- Define the top level container in our container hierarchy -->
    <!-- 在我們的容器體系中定義最高級別的容器 -->
    <Engine name="Catalina" defaultHost="localhost" debug="0">

      <!-- The request dumper valve dumps useful debugging information about
           the request headers and cookies that were received, and the response
           headers and cookies that were sent, for all requests received by
           this instance of Tomcat. If you care only about requests to a
           particular virtual host, or a particular application, nest this
           element inside the corresponding <Host> or <Context> entry instead.

           For a similar mechanism that is portable to all Servlet 2.4
           containers, check out the "RequestDumperFilter" Filter in the
           example application (the source for this filter may be found in
           "$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters").

           Request dumping is disabled by default. Uncomment the following
           element to enable it. -->
      <!-- 請求轉儲器值轉儲非常有用的通過Tomcat這個實例接收到的所有請求的,關于
           接收到的請求頭和cookies,以及發送出的回應頭和cookies的調試信息。如果
           你只在意一個特定的虛擬主機或者一個特定應用程序的請求,在對應的<Host>
           或<Context>入口中套用這個元素。
           
           對于所有的Servlet(小服務程序)2.4來所,在示例程序中檢驗
           “RequestDumperFilter”過濾是非常容易的(這個過濾器源代碼可以在
           “$CATALINA_HOME/webapps/examples/WEB-INF/classes/filters”下找到。
           
           請求轉儲默認情況下是關閉的,如果要使用它,取消下面行的注釋符。-->
      <!--
      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
      -->

      <!-- Global logger unless overridden at lower levels -->
      <!-- 全局日志設置,除非在更低的級別上覆蓋它的設置 -->
      <Logger className="org.apache.catalina.logger.FileLogger"
              prefix="catalina_log." suffix=".txt"
              timestamp="true"/>

      <!-- Because this Realm is here, an instance will be shared globally -->
      <!-- 因為這個Realm(區域)在這兒,因此這個實例將被全局共享。 -->

      <!-- 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(區域)使用在全局JNDI資源下,由“UserDatabase”配置的用戶
           數據庫。通過使用Realm將使對于這個用戶數據庫的任何編輯都將會立即可用
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                 debug="0" resourceName="UserDatabase"/>

      <!-- Comment out the old realm but leave here for now in case we
           need to go back quickly -->
      <!-- 注釋掉舊有的Realm以便我們能很快速的恢復舊有配置。 -->
      <!--
      <Realm className="org.apache.catalina.realm.MemoryRealm" />
      -->

      <!-- Replace the above Realm with one of the following to get a Realm
           stored in a database and accessed via JDBC -->
      <!-- 下面的屬性用于從儲存在數據庫或從JDBC通道中得到的Realm以取代上面的
           Realm配置。-->

      <!--
      <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
             driverName="org.gjt.mm.mysql.Driver"
          connectionURL="jdbc:mysql://localhost/authority"
         connectionName="test" connectionPassword="test"
              userTable="users" userNameCol="user_name" userCredCol="user_pass"
          userRoleTable="user_roles" roleNameCol="role_name" />
      -->

      <!--
      <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
             driverName="oracle.jdbc.driver.OracleDriver"
          connectionURL="jdbc:oracle:thin:@ntserver:1521:ORCL"
         connectionName="scott" connectionPassword="tiger"
              userTable="users" userNameCol="user_name" userCredCol="user_pass"
          userRoleTable="user_roles" roleNameCol="role_name" />
      -->

      <!--
      <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
             driverName="sun.jdbc.odbc.JdbcOdbcDriver"
          connectionURL="jdbc:odbc:CATALINA"
              userTable="users" userNameCol="user_name" userCredCol="user_pass"
          userRoleTable="user_roles" roleNameCol="role_name" />
      -->

      <!-- Define the default virtual host
           Note: XML Schema validation will not work with Xerces 2.2.
       -->
      <!-- 定義默認的虛擬主機
           注意:XML模式確認將不能與Xerces 2.2同工作。
      -->
      <Host name="localhost" debug="0" appBase="webapps"
       unpackWARs="true" autoDeploy="true"
       xmlValidation="false" xmlNamespaceAware="false">

        <!-- Defines a cluster for this node,
             By defining this element, means that every manager will be changed.
             So when running a cluster, only make sure that you have webapps in there
             that need to be clustered and remove the other ones.
             A cluster has the following parameters:
             為這個結點定義一個群集,通過定義這個元素,意味著每個管理員都將被改變。
             因此,當運行一個群集時,只有確認在必須被聚集和移除其他的地方有你的
             web軟件。
             一個群集有下面這些參數:

             className = the fully qualified name of the cluster class
             className = 這個群集類的全限定名

             name = a descriptive name for your cluster, can be anything
             name = 你的群集的描述名,可以是任何描述

             debug = the debug level, higher means more output
             debug = 調試級別,更高意味著更多的輸出

             mcastAddr = the multicast address, has to be the same for all the nodes
             mcastAddr = 多播地址,所有的節點都必須有同樣的多播地址

             mcastPort = the multicast port, has to be the same for all the nodes
             mcastPort = 多播端口,對所有的節點都必須有同樣的多播端口
             
             mcastBindAddr = bind the multicast socket to a specific address
             mcastBindAddr = 綁定多播套接字到一個指定的地址
             
             mcastTTL = the multicast TTL if you want to limit your broadcast
             mcastTTL = 多播生存期,如果你想要限制你的廣播的話
             
             mcastSoTimeout = the multicast readtimeout
             mcastSoTimeout = 多播讀取超時

             mcastFrequency = the number of milliseconds in between sending a "I'm alive" heartbeat
             mcastFrequency = 發送“I'm alive”(我還活著)信息的間隔毫秒數

             mcastDropTime = the number a milliseconds before a node is considered "dead" if no heartbeat is received
             mcastDropTime = 多長時間沒有收到“I'm alive”就將這個節點標識為死節點(單位:毫秒)

             tcpThreadCount = the number of threads to handle incoming replication requests, optimal would be the same amount of threads as nodes
             tcpThreadCount = 用于處理重復引入請求的線程數,最好是每個節點都有相同的線程數

             tcpListenAddress = the listen address (bind address) for TCP cluster request on this host,
                                in case of multiple ethernet cards.
                                auto means that address becomes
                                InetAddress.getLocalHost().getHostAddress()
             tcpListenAddress = 在有多塊以太網卡的主機上的監聽TCP群集請求的地址(綁定地址),
                                auto意味著地址由InetAddress.getLocalHost().getHostAddress()取得。

             tcpListenPort = the tcp listen port
             tcpListenPort = tcp監聽端口

             tcpSelectorTimeout = the timeout (ms) for the Selector.select() method in case the OS
                                  has a wakup bug in java.nio. Set to 0 for no timeout
             tcpSelectorTimeout = 在操作系統中有java.nio喚醒錯的情況下,使用Selector.select()的超時
                                  毫秒數。設為0則沒有超時限制

             printToScreen = true means that managers will also print to std.out
             printToScreen = true意味著管理員的相關信息也將打印輸出到std.out

             expireSessionsOnShutdown = true means that
             expireSessionsOnShutdown = true 意味著?????

             useDirtyFlag = true means that we only replicate a session after setAttribute,removeAttribute has been called.
                            false means to replicate the session after each request.
                            false means that replication would work for the following piece of code:
                            <%
                            HashMap map = (HashMap)session.getAttribute("map");
                            map.put("key","value");
                            %>
             useDirtyFlag = true意味著我們只能在調用setAttribute,removeAttribute后才能復制一個會話;
                            false意味著在每個請求后復制會話。
                            false意味著復制將以下列代碼方式工作:
                            <%
                            HashMap map = (HashMap)session.getAttribute("map");
                            map.put("key","value");
                            %>
                            
             replicationMode = can be either 'pooled', 'synchronous' or 'asynchronous'.
                               * Pooled means that the replication happens using several sockets in a synchronous way. Ie, the data gets replicated, then the request return. This is the same as the 'synchronous' setting except it uses a pool of sockets, hence it is multithreaded. This is the fastest and safest configuration. To use this, also increase the nr of tcp threads that you have dealing with replication.
                               * Synchronous means that the thread that executes the request, is also the
                               thread the replicates the data to the other nodes, and will not return until all
                               nodes have received the information.
                               * Asynchronous means that there is a specific 'sender' thread for each cluster node,
                               so the request thread will queue the replication request into a "smart" queue,
                               and then return to the client.
                               The "smart" queue is a queue where when a session is added to the queue, and the same session
                               already exists in the queue from a previous request, that session will be replaced
                               in the queue instead of replicating two requests. This almost never happens, unless there is a
                               large network delay.
             replicationMode = 可以是“pooled”、“synchronous”或者“asynchronous”
                               * Pooled意味著在多個套接字上同步進行復制。例如,先復制數據,然后請求返回。
                               這與“synchronous”相同,除了它使用一個套接字池,因此,它是多線程的。它是
                               最快和最高級的設置,使用這個配置也增加了處理復制的tcp線程的域。
                               * Synchronous指執行請求的線程,它也是向其他節點復制數據的線程,并且直到
                               所有的節點都己經收到信息后才返回。
                               * Asynchronous,對每個群集節點而言,這是一個特別的“sender”(發送者)線程,
                               因此請求線程將復制請求排隊到一個小隊列中,然后,返回給用戶。
                               這個小隊列是一個當會話被添加到隊列中,而從先前的請求中,同一個會話己經存在
                               ,這個會話將被放置在隊列中以代替重復的兩個請求。這幾乎從不會發生,除非存在
                               較大的網絡延遲。
        -->
        <!--
            When configuring for clustering, you also add in a valve to catch all the requests
            coming in, at the end of the request, the session may or may not be replicated.
            A session is replicated if and only if all the conditions are met:
            1. useDirtyFlag is true or setAttribute or removeAttribute has been called AND
            2. a session exists (has been created)
            3. the request is not trapped by the "filter" attribute

            The filter attribute is to filter out requests that could not modify the session,
            hence we don't replicate the session after the end of this request.
            The filter is negative, ie, anything you put in the filter, you mean to filter out,
            ie, no replication will be done on requests that match one of the filters.
            The filter attribute is delimited by ;, so you can't escape out ; even if you wanted to.

            filter=".*\.gif;.*\.js;" means that we will not replicate the session after requests with the URI
            ending with .gif and .js are intercepted.
        -->
        <!-- 當配置群集時,你也添加一個值來捕獲所有傳入的請求,在請求結束時,這個會話可能被子復制,
             也可能不被復制。一個會話是否復制取決于下列條件是否發生:
             1. useDirtyFlag為真,或者setAttribute或者removeAttribute己經被調用。
             2. 會話己經存在(己經被創建了)。
             3. 請求沒有被“filter”屬性所捕獲。
             
             這個filter(過濾器)屬性用于過濾那些不能修改會話的請求,因此,我們在這個請求結束后不復制
             會主。這個過濾器是消極的,例如,你向過濾器發送了一些東西,然后被過濾出去,在那個匹配的過
             濾器上不會發生復制。
             過濾器屬性以分號為分隔,因此你不能換行,即使你想這么做。
             
             filter=".*\.gif;.*\.js;"意味著在進行以.gif和.js結束的URI請求后不復制會話。
        
        <!--
        <Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.DeltaManager"
                 expireSessionsOnShutdown="false"
                 useDirtyFlag="true">

            <Membership
                className="org.apache.catalina.cluster.mcast.McastService"
                mcastAddr="228.0.0.4"
                mcastPort="45564"
                mcastFrequency="500"
                mcastDropTime="3000"/>

            <Receiver
                className="org.apache.catalina.cluster.tcp.ReplicationListener"
                tcpListenAddress="auto"
                tcpListenPort="4001"
                tcpSelectorTimeout="100"
                tcpThreadCount="6"/>

            <Sender
                className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
                replicationMode="pooled"/>

            <Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
                   filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
        </Cluster>
        -->



        <!-- Normally, users must authenticate themselves to each web app
             individually. Uncomment the following entry if you would like
             a user to be authenticated the first time they encounter a
             resource protected by a security constraint, and then have that
             user identity maintained across *all* web applications contained
             in this virtual host. -->
        <!-- 通常,對每一個應用程序,用戶必須逐個的認證他們自己。當他們遇到被
             某種安全約束所保護的資源時,如果你想讓用戶只在第一次被認證,那么,
             取消下面入口行的注釋,然后在這個虛擬主機中包含這個用戶的,橫跨所有
             web應用程序的用戶身份識別。-->
             
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn"
                   debug="0"/>
        -->

        <!-- Access log processes all requests for this virtual host. By
             default, log files are created in the "logs" directory relative to
             $CATALINA_HOME. If you wish, you can specify a different
             directory with the "directory" attribute. Specify either a relative
             (to $CATALINA_HOME) or absolute path to the desired directory.
        -->
        <!-- 這個虛擬主機的所有請求的訪問日志過程。默認情況下,日志文件被創建在相對
             于$CATALINA_HOME目錄下的logs目錄下。通過directory屬性,你也可以指定一個
             不同的目錄,如果你想的話。可以使用相對路徑(相對于$CATALINA_HOME),也
             可以使用絕對路徑。-->
        <!--
        <Valve className="org.apache.catalina.valves.AccessLogValve"
                 directory="logs" prefix="localhost_access_log." suffix=".txt"
                 pattern="common" resolveHosts="false"/>
        -->

        <!-- Logger shared by all Contexts related to this virtual host. By
             default (when using FileLogger), log files are created in the "logs"
             directory relative to $CATALINA_HOME. If you wish, you can specify
             a different directory with the "directory" attribute. Specify either a
             relative (to $CATALINA_HOME) or absolute path to the desired
             directory.-->
        <!-- 與這個虛擬主機有關系所有上下文所共享的日志。默認情況下(使用FileLogger時),
             日志文件被創建在相對于$CATALINA_HOME目錄下的logs目錄下。如果你希望,你也可
             以給directory指定一個不同的路徑。可以使用相對于$CATALINA_HOME的相對路徑,也
             可以使用絕對路徑。
        <Logger className="org.apache.catalina.logger.FileLogger"
                 directory="logs" prefix="localhost_log." suffix=".txt"
            timestamp="true"/>

      </Host>

    </Engine>

  </Service>

</Server>