Tomcat原理和配置详解

1 官方文档解读(持续更新)

官网https://tomcat.apache.org/tomcat-10.0-doc/

在开始之前,我们先安装一个Tomcat,这里安装的是apache-tomcat-10.0.23-windows-x64.zip

1.1 安装目录介绍

  • /bin - Startup, shutdown, 以及其他一些脚本
  • /conf - 配置文件和相关DTD. 其中最重要的是server.xml,它是容器的主要配置文件。
  • /logs - 日志文件
  • /webapps - web应用部署的地方

1.2 CATALINA_HOME和CATALINA_BASE

这是两个环境变量,我们可以配置也可以不配置。视情况而定。

CATALINA_HOME:Tomcat安装路径。包含了静态资源,比如.jar文件和二进制文件。

CATALINA_BASE:表示一个Tomcat实例的配置根路径。包含了配置文件、日志文件、部署的应用、以及一些其他运行时配置信息。对于一个CATALINA_BASE其最低配置是只包含conf/server.xml和conf/web.xml。

默认情况下,CATALINA_HOME和CATALINA_BASE是一个路径。

1.3 配置

<?xml version="1.0" encoding="utf-8" ?>
<Server port="8005" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JasperListener" />
    <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <GlobalNamingResources>
        <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 name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        <Engine name="Catalina" defaultHost="SpringMVC">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
            <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false"     
                 xmlNamespaceAware="false">
            <!--HelloMule-->
            <!--
                <Context path="/mule" docBase="/var/www/webapp/Mule"
                workDir="/var/www/webtemp/Mule" debug="5" reloadable="false"
                crossContext="true" />
            -->
            </Host>
            <Host name="SpringMVC" appBase="/var/www/webapp/SpringMVC"
                unpackWARs="true" autoDeploy="false" xmlValidation="false"
                xmlNamespaceAware="false" />
        </Engine>
    </Service>
</Server>

Tomcat是多实例的,每个Tomcat实例的配置在conf/server.xml中。

官方文档查看方式:1、官网https://tomcat.apache.org/tomcat-10.0-doc/config/index.html,2、tomcat安装路径下的webapps\docs\config\index.html

1 Server组件

Tomcat应用由许多可配置的组件组成,其中Catalina组件是其他组件的顶层容器,对应server.xml中的<Server>元素,因此它必须是配置文件中最外层的元素,且是唯一的外层元素。

属性:

AttributeDescription
className

实现了org.apache.catalina.Server interface接口的类. 如果没有指定,默认为org.apache.catalina.core.StandardServer.

address

 

port

等待shutdow命令的端口号. -1表示禁止执行shutdown命令.

portOffset

 

shutdown

停止Tomcat实例的命令,由指定的端口监听和接收.

utilityThreads

当前Catalina实例中可用的线程数

 其中port和shutdown是安装了tomcat后默认显式指定的。

子元素

<Service>
<GlobalNamingResources>

2 Service组件

<Service>元素表示Service组件,其是Catalina组件的子组件。Service组件表示一个或多个Connector组件的组合,这些组件共享一个Engine组件来处理传入请求。一个Server组件中可以有多个Service组件。

    <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        <Engine name="Catalina" defaultHost="SpringMVC">
            ...
        </Engine>
    </Service>

属性

AttributeDescription
className

实现了org.apache.catalina.Service接口的类,默认为org.apache.catalina.core.StandardService.

name

Service的显示名, 

子元素

<Executor>,线程池。供Service中的其他组件使用,有一些默认值,比如最小线程活动线程数,最大线程数等
<Connector>,可以有多个
<Engine>,只允许有一个

3 Connector组件

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

上面列出的<Connector>标签表示一个支持HTTP/1.1协议的Connector组件。该组件使得Catalina除了具有执行servlets和jsp的功能之外,还具有了作为独立web服务器的功能。

该组件的一个特定实例监听某一端口的连接请求。在一个Service组件中可以有多个Connector组件,这些Connector组件和一个特定的Engine组件相关联,它们转发请求到这个Engine组件,处理请求和生成响应。

每个传入的非异步请求在请求期间都需要一个线程,<Connector>标签的minSpareThreads属性可以设置最小线程数(默认是10),当请并发求数超过minSpareThreads所配置的值时,将会创建新的线程来接收请求。

<Connector>标签的maxThreads属性可以设置最大请求处理线程数(默认是200),这个属性决定了这个Connector能够并发处理的请求数。当请求并发数超过maxThreads所配置的值时,新的连接将会被放到Connector创建的等待队列里面。

<Connector>标签的maxConnections属性可以设置最大连接数(默认是8192),当请求数超过这个配置时,Connector将不能缓存这些请求,操作系统将会缓存多余的请求。

<Connector>标签的acceptCount属性可以设置操作系统最大请求队列大小(默认是100),当请求数超过这个配置时,请求将会被丢弃。

4 Engine组件

<Engine>元素必须在<Service>元素里面,并且在所有<Connector>元素后面。

Engine组件接收和处理Connectors组件转发而来的请求,并把响应传递给相应的Connector。

AttributeDescription
className

实现org.apache.catalina.Engine接口的类. 默认是org.apache.catalina.core.StandardEngine.

defaultHost

Engine组件下可以有多个<Host>子组件,根据http请求中的域名的不同来对应不同的<Host>(虚拟主机)来处理请求。当http请求中的域名没有对应的<Host>时,defaultHost就起作用了。

name

Engine组件的名称.

<Engine>可以有一个或多个<Host>子元素,表示这个Server组件的多个虚拟主机,且有一个<Host>子元素和<Engine>的defaultHost属性相对应。

5 Host组件

<Host>元素表示一个虚拟主机,Host组件必须是Engine的子组件。

有时候为了节省主机资源,一个ip我们绑定多个域名,比如szj1.com和szj2.com。当我们访问这两个域名时,DNS服务器将会把域名解析成真正的ip,然后请求将会被转发到这个ip。然后我们在这个主机上部署了Tomcat,在tomcat中我们配置了两个Host组件,也就是两个虚拟主机

<Host name="szj1.com" appBase="/data/webapps/szj1" />
<Host name="szj2.com" appBase="/data/webapps/szj2" />

每一个虚拟主机对应一个appBase是我们部署的web应用程序。

这样在外界看来,他们访问的是不同的网站,其实是一个主机。

属性:

AttributeDescription
appBase

web应用在虚拟主机上的基目录. 该目录下的web应用可能会被部署到该虚拟主机上. 可以是绝对路径,也可以是相对$CATALINA_BASE的相对路径. 默认值为webapps.

xmlBase

指包含该Host部署的应用程序的Context的xml文件路径。可以是绝对路径也可以是相对tomcat目录的相对路径。如果未指定将使用"conf//"

autoDeploy

指tomcat在运行时是否要定期检查有没有新的应用程序,如果true,tomcat会定期检查appBase 和xmlBase 目录,如果找到了会自动部署的web应用程序,默认为true

deployOnStartup

指tomcat在启动时是否应该自动部署来自该Host的web应用程序,默认为true

6 Context组件

<Context path="/mule" docBase="/var/www/webapp/Mule" workDir="/var/www/webtemp/Mule" />

<Context>元素表示一个运行在虚拟主机中的web应用,这个web应用有两种形式:1、war包,2、和war包解压之后有相同结构的目录。具体目录结构可在Servlet规范中找到。

<Context>元素是<Host>的子元素。在一个<Host>可以定义任意多个<Context>元素。但是不建议直接在<Host>里面配置<Context>。有更合适的配置方式。见下面

Context的定义方式

(1)直接在<Host>元素中定义,上面已经说过,不建议这么做。

(2)/META-INF/context.xml中配置。

(3)$CATALINA_BASE/conf/[enginename]/[hostname]/目录下(idea运行tomcat就是用的这种方式)

比较重要的属性:

path:url匹配,匹配到最合适的之后,会交由docBase路径指定的web应用中的映射文件找到合适的Servlet去处理。当没有匹配项时,默认交由path=""处理。

docBase:web应用的路径。

workDir:临时文件和目录的路径,如果未指定,默认为$CATALINA_BASE/work。

1.4 部署方式

在了解部署方式之前,我们先介绍一下上下文描述符:上下文描述符是一个简单的xml配置文件,其中包含了这个上下文的相关配置。

上下文描述符可以在如下路径下:

  1. $CATALINA_BASE/conf/[enginename]/[hostname]/[webappname].xml
  2. $CATALINA_BASE/webapps/[webappname]/META-INF/context.xml

文件1是以应用名称命名,文件2固定为context.xml

Tomcat启动时部署

1.5 idea部署tomcat的方式分析

 Edit Configiation进行配置Tomcat服务器和部署web应用

下图是配置Server页面,我们选择本机上安装的Tomcat8.5.81

 

 

 部署配置

 

 

 我们可以看一下上图中选择的这个Artifacts

 

 

 配置之后,我们点击运行。注意看一下打印的日志

E:\apache-tomcat-8.5.81\bin\catalina.bat run
[2022-08-08 04:00:33,861] Artifact springmvc-demo:war exploded: Waiting for server connection to start artifact deployment...
Using CATALINA_BASE:   "C:\Users\xxx\AppData\Local\JetBrains\IntelliJIdea2022.1\tomcat\06615320-a6e3-4b9e-b8fb-ca9e5c6083d2"
Using CATALINA_HOME:   "E:\apache-tomcat-8.5.81"
Using CATALINA_TMPDIR: "E:\apache-tomcat-8.5.81\temp"
Using JRE_HOME:        "C:\Program Files\Java\jdk1.8.0_211\jre"
Using CLASSPATH:       "E:\apache-tomcat-8.5.81\bin\bootstrap.jar;E:\apache-tomcat-8.5.81\bin\tomcat-juli.jar"
Using CATALINA_OPTS:   ""
Connected to the target VM, address: '127.0.0.1:49677', transport: 'socket'

我们可以看到CATALINA_BASE:C:\Users\xxx\AppData\Local\JetBrains\IntelliJIdea2022.1\tomcat\06615320-a6e3-4b9e-b8fb-ca9e5c6083d2,这是Tomcat实例的路径

 

 我们继续看conf/server.xml

<Host>的appBase为E:\apache-tomcat-8.5.81\webapps,表示web应用的位置,其中deployIgnore="^(?!(manager)|(tomee)$).*"表示忽略了的web应用,这里设置manager和tomee表示,除了这两个应用外,其他应用都不部署,具体部署哪个应用是在$CATALINA_BASE/conf/[enginename]/[hostname]/目录下配置的。下面会讲

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  <GlobalNamingResources>
    <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 name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" />
      </Realm>
      <Host name="localhost" appBase="E:\apache-tomcat-8.5.81\webapps" unpackWARs="true" autoDeploy="true" deployOnStartup="false" deployIgnore="^(?!(manager)|(tomee)$).*">
        <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>

$CATALINA_BASE/conf/Caltalina/localhost/springmvc_demo_war_exploded.xml

 <Context path="/springmvc_demo_war_exploded" docBase="D:\code\springmvc-demo\target\springmvc-demo" /> 

这里配置了部署的应用的位置docBase。还配置了url中的路径path。

$CATALINA_BASE/conf/web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee                       http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>0</param-value>
    </init-param>
    <init-param>
      <param-name>listings</param-name>
      <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
      <param-name>classdebuginfo</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>fork</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>xpoweredBy</param-name>
      <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
  ...省略

在web.xml文件中,配置了两个Servlet,名称分别是default和jsp,且这两个Servlet随Tomcat容器一起实例化。

我们知道servlet初始化时,会调用init(ServletConfig config)方法。在idea中调试的时候,我们会发现这个init方法调用了很多次,

下面列出了调试过程中打印的几个Servlet信息。

StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springmvc_demo_war_exploded].StandardWrapper[default]
StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springmvc_demo_war_exploded].StandardWrapper[dispatcher]
StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springmvc_demo_war_exploded].StandardWrapper[jsp]
StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springmvc_demo_war_exploded].StandardWrapper[jsp]
StandardEngine[Catalina].StandardHost[localhost].StandardContext[/manager].StandardWrapper[default]
StandardEngine[Catalina].StandardHost[localhost].StandardContext[/manager].StandardWrapper[jsp]

下面分析其原因:

上面我们已经知道,idea调试时除了会部署当前web应用外,还会部署manager应用,根据server.xml中的配置,我们知道,这两个应用都部署在当前的Tomcat实例中,且都部署在这个Tomcat实例的Engine名为Catalina,虚拟主机名Host为localhost中。但是这个虚拟主机下部署了两个不同的web应用,分别是springmvc_demo_war_exploded和manager,每个应用都配置了随Tomcat启动的若干个servlet。我们可以对照下图理解

 

 这些servlet初始化时都会调用init方法。这就是我们看到init被调用多次的原因。

 

 

总结:从这里,我们了解到,idea中启动一个tomcat实例,不会修改tomcat安装路径下的任何东西,真正做到了对tomcat安装路径零污染。

 

posted @ 2022-08-01 22:48  zhenjingcool  阅读(497)  评论(0编辑  收藏  举报