Tomcat之源码整体架构设计介绍

1.源码引入

1.1.1.server.xml:截图样例(整体的组件配置文件)

在这里插入图片描述

1.1.2.附带源文件:server.xml

<?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">
  <!-- 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 (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 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 a SSL HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation that requires the JSSE
         style configuration. When using the APR/native implementation, the
         OpenSSL style configuration is required as described in the APR/native
         documentation -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" 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 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 &quot;%r&quot; %s %b" />

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

1.1.3.层次结构图

在这里插入图片描述

2.整体架构图

2.1.通过上面的结构层级,得出下面的整体架构图架构图

在这里插入图片描述

2.2.整体架构图流程说明

首先我们需要理解的问题是:
1.图示中的每一个组件对应着源码中那个类图?
2.tomcat如何接收的?谁接收的?---->Connector
3.tomcat在处理的过程中如何进入到具体的servlet业务逻辑中进行处理? 

3.Tomcat架构中各个组件的含义

https://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

3.1.Server

3.1.1.类图示

在这里插入图片描述

3.1.2.概念

1.In the Tomcat world, a Server represents the whole container. Tomcat provides a default implementation of the 
  Server interface which is rarely customized by users.
  Server代表整个容器,Tomcat提供给了一个Server接口的默认实现,用户很少去自定义;
2.Server 可以认为是一个顶级的容器,启动了Server容器,其他的组件也就可以使用;  

3.2.Service

3.2.1.类图示

在这里插入图片描述

3.2.2.概念

A Service is an intermediate component which lives inside a Server and ties one or more Connectors to exactly one Engine. 
The Service element is rarely customized by users, as the default implementation is simple and sufficient: Service interface.
Service是一个运行在Server内部的一个中间组件,Service将一个或者多个Connector紧密的连接到Engine组件上面;
Service组件用户很少去自定义,默认的Service组件Service接口简单高效的;

3.2.Engine

3.3.1.类图示

在这里插入图片描述

3.3.2.概念

An Engine represents request processing pipeline for a specific Service. 
Engine代表特定服务的请求处理管道。
As a Service may have multiple Connectors, the Engine receives and processes all requests from these connectors,
 handing the response back to the appropriate connector for transmission to the client. 
由于服务可能具有多个Connectors,因此Engine会接收并处理来自这些Connectors的所有请求,
  将响应传递回适当的Connectors以传输到客户端。 
The Engine interface may be implemented to supply custom Engines, though this is uncommon.
尽快Engine自定义接口不太常见,当时Engine接口可以自定义的Engine接口实现,

3.4.Host

3.4.1.类图示

在这里插入图片描述

3.4.2.概念

A Host is an association of a network name, e.g. www.yourcompany.com, to the Tomcat server. 
Host是一个关联我们服务的网络的名字,比如www.yourcompany.com
An Engine may contain multiple hosts, and the Host element also supports network aliases 
such as yourcompany.com and abc.yourcompany.com. 
一个Engine可能包含多个Hosts,并且每个host可以配置不同的网络别名。比如as yourcompany.com 和 abc.yourcompany.com
Users rarely create custom Hosts because the StandardHost implementation provides significant additional functionality.
由于StandardHost接口实现非常的高效,用户很少创建自定义的hosts;

像我们平时启动了本地的tomcat服务之后,我们可以直接使用localhost这个host去访问,我们也可以配置其他的
在这里插入图片描述

3.5.Connector

3.5.1.类图示

在这里插入图片描述

3.5.2.概念

https://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html

1.A Connector handles communications with the client. 
  Connector负责与客户端的交互;
  There are multiple connectors available with Tomcat.
  Tomcat中有多个是可以使用connectors;
  These include the HTTP connector which is used for most HTTP traffic, especially when running Tomcat as 
  a standalone server, and the AJP connector which implements the AJP protocol used when connecting Tomcat to 
  a web server such as Apache HTTPD server. Creating a customized connector is a significant effort.
  这些Connectors包含Http类型的connector(比如:独立运行的tomcat服务)
  另外,AJP类型的Connector实现了AJP协议,(比如:tomcat连接Apache Httpd Server类型的web服务)
  创建定制的连接器是一项巨大的工作

在这里插入图片描述

3.5.2.源码流程

源码追溯,我们可以看到最终是ServerSocket进行监听
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.5.4.EndPoint

1.AbstractEndPoint:对于传输层协议的抽象,里面是写Socket代码的
2.JioEndPoint:同步阻塞IO,针对并发量比较大的时候,效率比较低,一个连接要一个线程
3.NIO:同步非阻塞IO,并发量比较大的时候,比较占优势,单独一个线程,处理并发
4.Apr:与本地方法库进行交互,  

在这里插入图片描述

3.5.5.关于协议类型的设置

在这里插入图片描述
tomcat8 默认是NIO模式
在这里插入图片描述

3.6.Context

3.6.1.类视图

在这里插入图片描述

3.6.2.概念

A Context represents a web application. A Host may contain multiple contexts, each with a unique path. 
Context代表一个web应用。一个Host可能包含多个Context,每一个Context有一个唯一的path地址
The Context interface may be implemented to create custom Contexts, but this is rarely the case 
because the StandardContext provides significant additional functionality.
Conext很少被自定义实现,因为默认的StandardContext接口提供了高效的功能;

3.5.3.源码流程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.6.4.Context的配置类ContextConfig:代表加载web.xml中的Servlet类

在这里插入图片描述

在这里插入图片描述

3.6.4.1.ContextConfig.webConfig()方法介绍
 /**
     * Scan the web.xml files that apply to the web application and merge them
     * using the rules defined in the spec. For the global web.xml files,
     * where there is duplicate configuration, the most specific level wins. ie
     * an application's web.xml takes precedence over the host level or global
     * web.xml file.
     * 扫描web.xml文件,将相关属性赋予到web应用中使其生效
     */
    protected void webConfig() {
        /*
         * Anything and everything can override the global and host defaults.
         * This is implemented in two parts
         * - Handle as a web fragment that gets added after everything else so
         *   everything else takes priority
         * - Mark Servlets as overridable so SCI configuration can replace
         *   configuration from the defaults
         */

        /*
         * The rules for annotation scanning are not as clear-cut as one might
         * think. Tomcat implements the following process:
         * - As per SRV.1.6.2, Tomcat will scan for annotations regardless of
         *   which Servlet spec version is declared in web.xml. The EG has
         *   confirmed this is the expected behaviour.
         * - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main
         *   web.xml is marked as metadata-complete, JARs are still processed
         *   for SCIs.
         * - If metadata-complete=true and an absolute ordering is specified,
         *   JARs excluded from the ordering are also excluded from the SCI
         *   processing.
         * - If an SCI has a @HandlesType annotation then all classes (except
         *   those in JARs excluded from an absolute ordering) need to be
         *   scanned to check if they match.
         */
        Set<WebXml> defaults = new HashSet<>();
        defaults.add(getDefaultWebXmlFragment());

        WebXml webXml = createWebXml();

        // Parse context level web.xml
        InputSource contextWebXml = getContextWebXmlSource();
        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
            ok = false;
        }

        ServletContext sContext = context.getServletContext();

        // Ordering is important here

        // Step 1. Identify all the JARs packaged with the application and those
        // provided by the container. If any of the application JARs have a
        // web-fragment.xml it will be parsed at this point. web-fragment.xml
        // files are ignored for container provided JARs.
        Map<String,WebXml> fragments = processJarsForWebFragments(webXml);

        // Step 2. Order the fragments.
        Set<WebXml> orderedFragments = null;
        orderedFragments =
                WebXml.orderWebFragments(webXml, fragments, sContext);

        // Step 3. Look for ServletContainerInitializer implementations
        if (ok) {
            processServletContainerInitializers(sContext);
        }

        if  (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
            // Step 4. Process /WEB-INF/classes for annotations and
            // @HandlesTypes matches
            if (ok) {
                WebResource[] webResources =
                        context.getResources().listResources("/WEB-INF/classes");

                for (WebResource webResource : webResources) {
                    processAnnotationsWebResource(webResource, webXml,
                            webXml.isMetadataComplete());
                }
            }

            // Step 5. Process JARs for annotations for annotations and
            // @HandlesTypes matches - only need to process those fragments we
            // are going to use (remember orderedFragments includes any
            // container fragments)
            if (ok) {
                processAnnotations(
                        orderedFragments, webXml.isMetadataComplete());
            }

            // Cache, if used, is no longer required so clear it
            javaClassCache.clear();
        }

        if (!webXml.isMetadataComplete()) {
            // Step 6. Merge web-fragment.xml files into the main web.xml
            // file.
            if (ok) {
                ok = webXml.merge(orderedFragments);
            }

            // Step 7. Apply global defaults
            // Have to merge defaults before JSP conversion since defaults
            // provide JSP servlet definition.
            webXml.merge(defaults);

            // Step 8. Convert explicitly mentioned jsps to servlets
            if (ok) {
                convertJsps(webXml);
            }

            // Step 9. Apply merged web.xml to Context
            if (ok) {
                configureContext(webXml);
            }
         } else {
            webXml.merge(defaults);
            convertJsps(webXml);
            configureContext(webXml);
        }

        // Step 9a. Make the merged web.xml available to other
        // components, specifically Jasper, to save those components
        // from having to re-generate it.
        // TODO Use a ServletContainerInitializer for Jasper
        String mergedWebXml = webXml.toXml();
        sContext.setAttribute(
               org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML,
               mergedWebXml);
        if (context.getLogEffectiveWebXml()) {
            log.info("web.xml:\n" + mergedWebXml);
        }

        // Always need to look for static resources
        // Step 10. Look for static resources packaged in JARs
        if (ok) {
            // Spec does not define an order.
            // Use ordered JARs followed by remaining JARs
            Set<WebXml> resourceJars = new LinkedHashSet<>();
            if (orderedFragments != null) {
                for (WebXml fragment : orderedFragments) {
                    resourceJars.add(fragment);
                }
            }
            for (WebXml fragment : fragments.values()) {
                if (!resourceJars.contains(fragment)) {
                    resourceJars.add(fragment);
                }
            }
            processResourceJARs(resourceJars);
            // See also StandardContext.resourcesStart() for
            // WEB-INF/classes/META-INF/resources configuration
        }

        // Step 11. Apply the ServletContainerInitializer config to the
        // context
        if (ok) {
            for (Map.Entry<ServletContainerInitializer,
                    Set<Class<?>>> entry :
                        initializerClassMap.entrySet()) {
                if (entry.getValue().isEmpty()) {
                    context.addServletContainerInitializer(
                            entry.getKey(), null);
                } else {
                    context.addServletContainerInitializer(
                            entry.getKey(), entry.getValue());
                }
            }
        }
    }

在这里插入图片描述

在这里插入图片描述

呼应了Wrapper=Servlet

4.关于组件对内对外属性

4.1.Connector:是对外的交互的

4.2.Contanier:Engine,Context,Host,Wrapper(Servlet) 是对内交互的

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东山富哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值