揭开Tomcat的神秘面纱

了解tomcat

总所周知,我们的web应用在上线时都要将web应用打包成一个war包到tomcat的目录下进行解压。然后通过浏览器去发URL的请求。那么请求必定是要先经过Tomcat 的。那么Tomcat拿到请求后是如何应对的呢?

手写 tomcat 配置文件

所有的服务器都有他自己的属性,当然 tomcat 也不例外。无轮任何应用想要与外界通讯必须就要去管理自己的端口,所以tomcat的属性配置文件server.xml文件诞生了。这个文件集中管理了tomcat的属性配置。

server.xml 配置文件在 tomcat 目录下的conf 目录下,我们先大概了解一下tomcat的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- 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>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <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
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation. The default
         SSLImplementation will depend on the presence of the APR/native
         library and the useOpenSSL attribute of the
         AprLifecycleListener.
         Either JSSE or OpenSSL style configuration may be used regardless of
         the SSLImplementation selected. JSSE style configuration is used below.
    -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->
    <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
         This connector uses the APR/native implementation which always uses
         OpenSSL for TLS.
         Either JSSE or OpenSSL style configuration may be used. OpenSSL style
         configuration is used below.
    -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         certificateChainFile="conf/localhost-rsa-chain.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->

    <!-- 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 name="Catalina" defaultHost="localhost">

      <!--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"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- 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"/>
      </Realm>

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

        <!-- 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
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

顶层元素: Server和Service标签
是整个配置文件的根元素,可以与一组和一个相连。

所以我们可以写出如下的一种配置结构

<server> 
 <Service>
 <Connector></Connector>
 <Connector></Connector>
 <Connector></Connector>
 <Engine></Engine>
 </Service>
</server>
<Server>

我们在 Server 标签中 可以配置 port=”8005″ shutdown=”SHUTDOWN” shutdown属性表示官兵Server服务,port 表示接受shutdown指令的端口号,只要将 port = “-1” 即可禁掉该端口.

<server port="8005" shutdown="SHUTDOWN"> 
 <Service>
 <Connector></Connector>
 <Connector></Connector>
 <Connector></Connector>
 <Engine></Engine>
 </Service>
</server>

Server 的主要作用是提供一个让客户端可以访问 Service 的接口,同时对 service 进行维护和管理,包括Service的初始化,运行,销毁以及找到客户端要找的Service。

Service中有一个 name=”Catalina” 属性,因为tomcat可以提供多个服务,所以这个属性是它的 标识名 .

<server port="8005" shutdown="SHUTDOWN"> 
 <Service name= "Catalina">
 <Connector></Connector>
 <Connector></Connector>
 <Connector></Connector>
 <Engine></Engine>
 </Service>
</server>

Service 的主要作用是将 Connector 和 Engine 组合在一起。 Service可有包含多个 Connector 但是只能有一个 Engine

连接器: Connector
Connector 代表了外部客户端发送请求到特定的Service接口,同时也是从外部接受请求的特定接口。它创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine进行处理,并把 Request和Response对象 传给Engine。

port=”8080″ protocol=”HTTP/1.1″ connectionTimeout=”20000″
redirectPort=”8443″ ;port 应该很熟悉了,8080是我们对外开放的端口,我们服务器通常开放的端口是80 而tomcat通常是不需要直接对外开放的,而是使用nginx等服务器来做代理。 protocol 属性这里是监听的http请求,也可以配置AJP协议,AJP协议是负责Tomcat与Apache等集成。 connectionTimeout 连接超时的时间, redirectPort 重定向端口。

<server port="8005" shutdown="SHUTDOWN"> 
 <Service name= "Catalina">
 <Connector port="8080" protocol="HTTP/1.1"   connectionTimeout="20000"
  redirectPort="8443"></Connector>
 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
 <Engine></Engine>
 </Service>
</server>

容器:Engine Host Context
Engine容器的功能是处理请求并返回。Engine 从一个或多个 Connector 中接收请求处理后返回给 Connector . Host Context 是 Engine 的子容器

name=”Catalina” defaultHost=”localhost” ; name属性用于日志和错误信息,整个Server应该唯一。 defaultHost 指定默认的host名字,当发往本机的host不存在时使用默认的host。并且 defaultHos 必须与 Host中的一个name属性匹配。

<server port="8005" shutdown="SHUTDOWN"> 
 <Service name= "Catalina">
 <Connector port="8080" protocol="HTTP/1.1"   connectionTimeout="20000"
  redirectPort="8443"></Connector>
 <Connect1111111111111111111111111111or port="8009" protocol="AJP/1.3" redirectPort="8443" />
 <Engine name="Catalina" defaultHost="localhost">
 <Host></Host>
 <Context></Context>
 </Engine>
 </Service>
</server>
<Host>

Host 组件代表虚拟主机,是运行多个Web应用(一个Context代表一个web应用),并负责安装,展开,启动,结束每个web应用。

Host 代表一个虚拟主机,对应服务器中一个网络实体(www.mmmnnaa.com,106.106.106.25)为了可以使用网络名连接Tomcat ,需要在DNS服务器上注册。

客户端通常使用主机名来标识他们希望连接的服务器;,将主机名包含在http请求的头部。tomcat从中提取出主机名,寻找匹配的主机,如果没有匹配,将请求发送到默认主机。

name=”localhost” appBase=”webapps” unpackWARs=”true” autoDeploy=”true” name属性指定虚拟主机名,appBase指定我们的应用部署的位置 unpackWars 表示是否解压war包 如果unpackWars = “false”,则不进行解压,直接使用war包运行。

<server port="8005" shutdown="SHUTDOWN"> 
 <Service name= "Catalina">
 <Connector port="8080" protocol="HTTP/1.1"   connectionTimeout="20000"
  redirectPort="8443"></Connector>
 <Connect1111111111111111111111111111or port="8009" protocol="AJP/1.3" redirectPort="8443" />
 <Engine name="Catalina" defaultHost="localhost">
 <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true"></Host>
 <Context></Context>
 </Engine>
 </Service>
</server>
<Context>

未完待续。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章