A, principle

1. Browser access server process

    1. The user enters the request into the browser
    2. The browser sends a TCP connection request
    3. The server receives the request (ignoring the case of NGINX etc.) and shakes hands three times to establish the connection
    4. The browser generates the HTTP packet and sends it
    5. The server receives and parses it
    6. The server executes the request and encapsulates the result sent
    7. The browser receives the packet in HTTP format and parses the rendering

2. Tomcat request processing process

First, Tomcat is an HTTP server

The HTTP server in Tomcat (the Connectot component) receives the request and passes it to the Servlet container (the Conntainer component) to process it (decoupling), and the Servlet container invokes the business class through the Servlet interface. The set of contents of the Servlet container is called the Servlet specification

3. Servlet container processing process

  1. The HTTP server wraps the request information in a ServletRequest object
  2. Depending on the configuration, find the mapping between the URL and the Servlet, and invoke a specific Servlet in the Servlet container
  3. If the Servlet is not already loaded, the Servlet is created using reflection and the init method of the Servlet is called to complete the initialization
  4. The service method of this Servlet is called to process the request, and the result is encapsulated in a ServletResponse object
  5. The ServletResponse object is returned to the HTTP server, which sends the response to the client

Second, the component

1. Connector component Coyote

The client establishes a connection with the server through Coyote, sending and responding to requests

  1. Coyote encapsulates underlying network communication (Socket request and response processing)
  2. Coyote decouples the Catalina container (container component) from specific requests and I/O operations
  3. Coyote wraps the Request object around the Socket input, and after the container processes it, Catelina writes the result to the output stream through the Response object
  4. Coyote is responsible for specific application layer protocols and transport layer IO

    ### 2. Servlet container Catalina

Tomcat is a Web container made up of a series of configurable (server.xml) components, with Catalina as its Servlet container. In a way, Tomcat is a Servlet container, with Catalina as its core component.

III. Core configuration

The configuration file server.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 根元素,定义一个Server实例,自己标签:Listener、GlobalNamingResources、Service-->
<!-- 监听8005,状态为关闭状态 这里不需要改-->
<Server port="8005" shutdown="SHUTDOWN">
  <!-- 定义监听器 以下都无需更改-->
  <!-- 打印JVM、操作系统相关日志 无需更改 -->
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- 加载销毁Apr 无需更改 -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- 避免JRE内存溢出 -->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <!-- 加载和停止全局命名服务 -->
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <!-- 在Context停止时重建 Executor 池中的线程,避免 ThreadLocal 相关的内存泄漏 -->
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- 定义全局JNDI资源 一般无需修改-->
  <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服务容器,一个server可以有很多service -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    
    <!-- 配置Service共享线程池 -->
    <!-- 默认情况下,Service 并未添加共享线程池配置。 如果我们想添加一个线程池, 可以在 <Service> 下添加如下配置: 
          name: 线程池名称,用于 Connector中指定
          namePrefix: 所创建的每个线程的名称前缀,一个单独的线程名称为 namePrefix+threadNumber
          maxThreads: 池中最大线程数 
          minSpareThreads: 活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在 
          maxIdleTime: 线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒
          maxQueueSize: 在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值 不需要更改,否则会有请求不会被处理的情况发生 prestartminSpareThreads: 启动线程池时是否启动 minSpareThreads部分线程。默认值为false,即不启动 
          threadPriority: 线程池中线程优先级,默认值为5,值从1到10 
          className: 线程池实现类,未指定情况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想使用自定义线程池首先需要实现 org.apache.catalina.Executor接口
    -->
    <Executor 
      name="commonThreadPool"
      namePrefix="thread-exec-"
      maxThreads="200"
      minSpareThreads="100"
      maxIdleTime="60000"
      maxQueueSize="Integer.MAX_VALUE" 
      prestartminSpareThreads="false"
      threadPriority="5" 
      className="org.apache.catalina.core.StandardThreadExecutor"
      />
 
    <!-- 一个Service容器可以有多个连接器,每个连接启动一个线程 -->
    <!-- 
      port: 端口号,Connector 用于创建服务端Socket 并进行监听,以等待客户端请求链接。如果该属性设置为0,Tomcat将会随机选择一个可用的端口号给当前Connector使用
      protocol: 当前Connector 支持的访问协议。默认为 HTTP/1.1,并采用自动切换机制选择一个基于 JAVA NIO的链接器或者基于本地APR的链接器根据本地是否含有Tomcat的本地库判定) 
      connectionTimeOut: Connector 接收链接后的等待超时时间, 单位为毫秒。 -1 表示不超时。 
      redirectPort: 当前Connector不支持SSL请求,接收到了一个请求,并且也符合security-constraint约束,需要SSL传输,Catalina自动将请求重定向到指定的端口。
      executor: 指定共享线程池的名称, 也可以通过maxThreads、minSpareThreads 等属性配置内部线程池。
      URIEncoding: 用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 , Tomcat7.x版本默认为ISO-8859-1
    -->
    <!--org.apache.coyote.http11.Http11NioProtocol , 非阻塞式 Java NIO 链接器--> 
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <!-- 使用共享线程池,不明确线程池就会有自己维护的线程池,造成资源浪费 -->
    <!-- 
    <Connector port="8080" 
               protocol="HTTP/1.1"
               executor="commonThreadPool" 
               maxThreads="1000" 
               minSpareThreads="100" 
               acceptCount="1000" 
               maxConnections="1000" 
               connectionTimeout="20000" 
               compression="on" 
               compressionMinSize="2048" 
               disableUploadTimeout="true" 
               redirectPort="8443" 
               URIEncoding="UTF-8" /> -->
    
 
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Servlet引擎 -->
    <!--
      name: 用于指定Engine的名称, 默认为Catalina
      defaultHost: 默认使用的虚拟主机名称,当客户端请求指向下边配置Host的主机无效时,将交由默认的虚拟主机处理,默认为localhost
    -->
    <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标签用于配置虚拟主机 -->
      <!-- 默认处理 ,appbase是相对路径,unpackWARs解压war包,autoDeploy自动部署-->
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <!-- 访问请求日志的 阀  ,存放路径为相对路径-->
        <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>

      <!-- 监听 www.abc.com:8080 -->
      <Host name="www.abc.com"  appBase="webapps1"
            unpackWARs="true" autoDeploy="true">

        <!--
        docBase:Web应用目录或者War包的部署路径。可以是绝对路径,也可以是相对于 Host appBase的 相对路径。
        path:Web应用的Context 路径。如果我们Host名为localhost, 则该web应用访问的根路径为: http://localhost:8080/web_demo。
        -->
        <Context docBase="/Users/yingdian/web_demo" path="/web3"></Context>

        <!-- 访问请求日志的 阀  ,存放路径为相对路径-->
        <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>