文档章节

Tomcat之图文解析Server.xml配置

Dylan1009
 Dylan1009
发布于 2017/03/28 22:16
字数 3641
阅读 112
收藏 2

    摘要: 本文会对Tomcat进行简单说明,作为后续配置web.xml的铺垫。说明主要围绕server.xml这一配置文件进行。

本文隶属于新手图文教程《IDEA+Maven搭建Spring+SpringMVC+Mybatis项目骨架》

下一篇:还没写好

目录 & 项目地址:http://git.oschina.net/mzdbxqh/ssm-study/

本文即将介绍的是Server.xml - Tomcat的主配置文件。该文件存放在安装目录下的conf文件夹中。为了让大家有个直观的认识,在此将Tomcat7的默认配置摘录如下:

<?xml version='1.0' encoding='utf-8'?>

<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.JasperListener" />
  <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" />
    <Connector port="8009" protocol="AJP/1.3" 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="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>
			
    </Engine>
  </Service>
</Server>

去掉元素属性,稍加整理,配置文件就变成了下面这样:

<Server> <!-- 顶级元素 -->
  <Listener/> <!-- 组件 -->
  <GlobalNamingResources/> <!-- 组件 --> 
  <Service> <!-- 另一个顶级元素 -->
    <Connector/> <!-- 接头 -->
    <Engine> <!-- 容器 -->
      <Realm/> <!-- 组件 -->
      <Host> <!-- 容器 -->
        <Valve/> <!-- 组件 -->
          <Context></Context> <!-- 容器 -->
      </Host>
    </Engine>
  </Service>
</Server>

根据Tomcat自身的分类,上面这些元素可以分成四种:

  1. 顶级元素 - 即Server和Service,前者是本配置文件的根节点,后者则起到了一个包裹内部组件的作用。换句话说,它们都属于“单纯的、不具有具体职能的配置节点”。
  2. 容器 - Tomcat内真正负责处理请求并返回结果的组件。
  3. Connector - Connector(接头)是一个特殊的组件,如果说整个Tomcat是一堵墙,它就是安装在墙上的插座。外部的客户端通过这些插座来跟Tomcat建立联系。
  4. 嵌套组件 - 这是一些嵌套在各种容器内部的组件,有些可以放在任意一层容器内,例如Listener;有些只能放在固定的位置,例如GlobalNamingResources。

下面将选择性地介绍这些元素。

一、顶级元素

1. Server

一个Tomcat只有一个Server.xml,即一个Tomcat实例只有一个Server。从实现来看,作为Server.xml的根节点,它不是一个容器,它只是单纯地扮演着一个包裹的角色。从命名来看,它又可以是整个Tomcat所有容器和作用于所用容器的组件的混合体。在此,我们把它当做是Tomcat实例本身。

★ 单机Tomcat实例个数

大部分情况下我们在一台服务器/云服务器上只跑一个tomcat,但也有两种特例:

一是为了测试,在一台机器上跑多个Tomcat,用以模拟多台服务器多个应用交互的效果。

二是通过nginx+多个tomcat组成负载均衡集群,以达到以下目的:

  1. 在32位系统上,由于寻址空间、内核预留内存等我们不太需要关心的机制,单个进程可以使用的内存上限大概是1.5G~2G(windows)和2G~3G(linux)。因此,大内存服务器上如果要充分利用内存就只能多开Tomcat。理论上64位系统没有这个问题。
  2. 配置太大的内存可能会降低JVM进行垃圾回收的频率,也就意味着每一次垃圾回收都是一个耗时日久的大工程,甚至可能导致宕机。一般建议单个JVM最大内存不超过1.5G。
  3. 从稳定性上考虑,个别tomcat挂了也不会导致服务下线。

Nginx+Tomcat

★ Server元素属性

<Server port="8005" shutdown="SHUTDOWN" />

Server可配置的属性很少。根据上面摘录的默认配置,Server会侦听localhost的TCP端口8005,当该端口接收到字符串"SHUTDOWN"时,即执行关闭Tomcat操作。

★ Server的嵌套组件

Server有两种特有的组件,一个是GlobalNamingResources(全局命名资源),一个是Service(服务)。除此之外,还可以有Listener(监听器)这种可以作用于不同层次容器的组件。Server默认配置了六种Listener,其作用会在后面介绍。配置在Server这一层的Listener对所有容器起作用。

Server元素组件

2. Service

Service是另一个混合体。一个Service就是一个完整的服务,负责将若干个Connector和一个Engine(引擎)包裹在一起。除此之外,Service还可以配置一个Executor(共享线程池)用于管理所有Connector的线程数量。

★ service元素属性

<Service name="Catalina">...</Service>

Service的属性比Server更少,一般只用到了name这个属性。默认配置定义了一个名为“Catalina”的 Service。什么是Catalina呢?Cataline是一个太平洋小岛的名字,而Tomcat开发团队的一个核心人员Craig McClanahan喜欢这个小岛,所以...

★ Service的嵌套组件

Service元素组件

如图所示,Service有Executor、Connector和Engine三种组件。其中,每个Connector负责侦听一个TCP端口,接收相应的请求,并转发给绑定的Engine处理。Engine处理完后,通过Connector把结果返回给客户端。在配置了Executor的情况下,所有Connector的线程受Executor统一管理。

二、容器

Tomcat里有四种层次的容器:Engine、Cluster、Host、Context,从属关系为:

Context -> (Cluster in Host) -> Host -> (Cluster in Engine) -> Engine

具体关系如下图所示:

Tomcat容器层次

1. Engine容器

Engine是Service的请求处理引擎,负责处理所有Connector发过来的请求,并将内部处理完毕的结果返回给Connector。它是最外层的容器。

★ Engine元素属性

<Engine name="Catalina" defaultHost="localhost" />

■ Engine.name - 引擎的名称

默认配置定义了一个Engine,和外层的Service一样,也叫Catalina。反正一个Service只有一个Engine,这么起名问题也不大。

■ Engine.defaultHost - 默认采用哪一个子容器Host来处理请求

■ Engine.jvmRoute - 一个用于负载均衡场景下的唯一标识符

默认的负载均衡场景下,Tomcat采用一种被称作粘性session的机制管理session信息。

粘性session就是将用户“粘”在其中一个Engine上。比方说,客户端刚访问进来时被Nginx转发到Engine#1并完成了登录验证,那么接下来的每次请求都应该转发到这个Engine。如果该机制失效,客户端的后续访问被Nginx转发到Engine#2的话,由于Engine#2并没有该客户端的session信息,将会要求重新登录。

为了实现粘性session,Engine需要告诉Nginx,某一个session是我处理的,后续这个session都要发给我。方法就是给Engine定义一个唯一的jvmRoute,附在它受理的sessionID上,再返回给Nginx。例如,配置jvmRote="Engine#1"。更多属性说明请参照官方文档:参考链接

★ Engine上下文配置

每一个Engine都在安装目录的conf文件夹下有一个对应的二级目录,例如默认的conf/cataline。相应的,Engine下的每一个Host,都会在Engine对应的二级目录下有一个三级目录,例如默认的conf/cataline/localhost。其路径规则为:

conf/<engine_name>/<host_name>

作用于整个Engine或整个Host的上下文信息可以配置在这些个目录中。该目录可以通过相应容器的xmlBase属性进行修改。

2. Host容器

一个Host就是一个虚拟主机,对应一个或多个域名。

★ Host元素属性

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

■ Host.name - 主机名称(域名)

默认配置定义了一个名为 localhost 的主机。至少要有一个Host的名称与Engine的defaultHost一致。

除了域名外,Host可以通过子节点alias来配置别名。别名的作用与域名一致。例如:

<Host name="www.a.com" ...>
  ...
  <Alias>a.com</Alias>
  <Alias>blog.a.com</Alias>
  <Alias>c.com</Alias>
  ...
</Host>

其作用机制如下图所示:

Engine根据域名转发请求

■ Host.appBase - 虚拟主机的根目录

该参数的默认值为webapps。一般情况下,每一个 webapp 的 URL 和它所在的目录名称相同。以webapps目录下的manager和docs两个程序为例(ROOT是个例外):

# 目录名即路径名
webapps/manager:http://localhost:8080/manager
webapps/docs:http://localhost:8080/docs
# 特例 - ROOT等于空字符串
webapps/ROOT:http://localhost:8080/

■ Host.unpackWARs - 放到 webapps 目录下的 WAR-file 是否应该被解压

如设为false,Tomcat 将会直接从 *.war文件运行应用,但可能导致应用运行变慢。

■ Host.autoDeploy - 是否自动部署放到 webapps 目录下的应用

3. Context容器

Context代表Host下面的一个虚拟目录。

在不配置Context的情况下是这样的:

If HostName:my.oshina.net
-> HostUrl:http://my.oschina.net/
So Brower:http://my.oschina.net/mzdbxqh
-> 访问:webapps/mzdbxqh

现在配置一个Context,同样访问博客域名,就变成了访问"D:/mzdbxqh"

<Context path="mzdbxqh" docBase="D:/mzdbxqh" debug="0" reloadable="true" crossContext="true"/>

★ Context元素属性

■ Context.docBase - 应用程序的路径或者是WAR文件存放的路径

■ Context.path - 此web应用程序的上下文路径

配置后,Context的访问url为:http://localhost:8080/path/

path为空的话,访问url为:http://localhost:8080/

■ Context.reloadable - 是否支持热部署

如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,并通过类加载器重新加载class文件,以实现在不重启tomcat的情况下重新部署。

因为配置文件基本是在web程序启动时一次性载入内存的,故一般来说Tomcat的热部署对配置文件无效。另外,只有新创建实例时才会向类加载器请求重新加载过的class,因此,Tomcat的热部署对于使用Spring管理的单例也是无效的。这两种情况需要web应用程序配合着写热部署的业务逻辑才能实现。

关于类加载器的相关内容可以阅读前面的章节

■ Context.crossContext - 不同context是否共享session

注意,这个跨应用共享session跟Cluster集群是不一样的。前者是指可以通过ServletContext.getContext()交叉访问其他Context的session,后者默认配置下是采用服务器session复制的方式,将每一个节点的session变动复制到所有节点。

更多属性说明请参照官方文档:参考链接

4. Cluster容器

Tomcat的Cluster是一个集群容器。它的集群策略是复制session,把集群内一个容器的session变动通过广播复制到其他所有容器上。Cluster可配置在Engine或Host内。如果读者需要使用该容器,一般来说已经不是新手了,请自行阅读官方文档:参考链接

此外,复制session的模式因为对网络(广播复制)和内存(每一个JVM实例都要保存所有在线用户的session)的负担较大,在大型分布式场景下一般采用session共享的方式。具体可以了解一下Spring Session。以上三种session管理方式的对比如下图所示:

session管理

三、其他

1. Connector组件

开头说过,Connector就是墙上的插座,负责侦听一个具体的TCP端口,并通过该端口处理Engine与客户端之间的交互。默认配置定义了两个 Connector:

<!--HTTP/1.1:处理 HTTP 请求,使得 Tomcat 成为了一个 HTTP 服务器。客户端可以通过 Connector 向服务器发送 HTTP 请求,接收服务器端的 HTTP 响应信息。-->
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<!--connectionTimeOut 属性定义了这个 connector 在链接获得同意之后,获得请求 URI line(请求信息)响应的最大等待时间毫秒数。默认为20秒。redirect 属性会把 SSL 请求重定向到 TCP 的8443端口。-->

<!--AJP/1.3:Apache JServ Protocol connector 处理 Tomcat 服务器与 Apache HTTP 服务器之间的交互。-->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

更多Connector和Executor线程池的配置会在Tomcat性能调优的章节进行说明。

2. Valve组件

Valve的中文含义是阀门,可以简单地理解为Tomcat的拦截器。它负责在请求发送到应用之前拦截HTTP请求,可以定义在任何容器中。默认配置中定义了一个AccessLogValve,负责拦截HTTP请求,并写入到日志文件中。

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

3. Listener组件

Listener即监听器,负责监听服务器端的行为。此处需要了解的监听器有两个:

<!--作用于 Jasper JSP 引擎,该引擎负责对更新后的 JSP 页面进行重编译。-->
<Listener className="org.apache.catalina.core.JasperListener" />
<!--作用于全局资源,保证 JNDI 对资源的可达性,比如数据库。-->
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

4. Realm组件

Realm提供了一种用户密码与web应用的映射关系。tomcat自带的manager管理工具就是根据conf/tomcat-users.xml中定义的账号来实现登录的。我们一般通过Shiro来实现,此处不作解释。

5. GlobalNamingResources组件

全局命名资源(过JNDI实现,相当于一台交换机,可以通过地址名访问各种系统外部资源。例如,通过一个名称,访问预设置好的一个Mysql连接池)。默认定义了一个名称为UserDatabase的JNDI,通过“conf/tomcat-users.xml”得到了一个用于用户授权的内存数据库。我们一般通过Spring进行管理,此处不作解释。

四、Tomcat处理Http请求的过程

请求地址为:http://my.oschina.net/mzdbxqh

  1. 请求通过DNS发送到指定主机的80端口,被负责侦听80端口的HTTP/1.1 Connector拦截
  2. Connector把请求转发给所在的Service的Engine,并等待Engine的回应
  3. Engine获得请求my.oschina.net/mzdbxqh,匹配它所拥有的所有虚拟主机Host
  4. Engine匹配到名为my.oschina.net的Host
    • 如果匹配不到就交给defaultHost
  5. 匹配的Host获得请求/mzdbxqh,匹配它所拥有的所有Context
  6. Host匹配到path为mzdbxqh的Context
    • 如果匹配不到就尝试匹配Path为""的Context
    • 如果还匹配不到就尝试到appBase参数对应的目录下找mzdbxqh文件夹
  7. 匹配的Context获得请求/,匹配web.xml中配置的Servlet
    • 如果匹配不到就尝试匹配Welcome-file-list
  8. Context匹配到url-pattern为"/"的servlet,对应于org.springframework.web.servlet.DispatcherServlet
  9. SpringMVC处理请求(后面章节再说),返回HttpServletResponse
  10. Context把HttpServletResponse对象返回给Host
  11. Host把HttpServletResponse对象返回给Engine
  12. Engine把HttpServletResponse对象返回给Connector
  13. Connector把HttpServletResponse对象返回给客户端

太长了先不画图了,就先这样吧。

本文转载自:https://my.oschina.net/mzdbxqh/blog/868011

上一篇: Spring面试总结
Dylan1009
粉丝 5
博文 195
码字总数 131086
作品 0
广州
程序员
私信 提问
tomcat6.0.x启动过程-tomcat 6.x 源码阅读

2013-09-07 周末来啊,宅的日子又到了...我们知道tomcat的基本是容器,通过容器来完成servlet容器的设计。从上一篇blog中看到了tomcat的结构框架图,图中容器嵌套,组件组合,tomcat如何设置...

douglaswei
2013/09/07
397
2
阿里云下载的https 证书在tomcat 上安装教程

文章是在阿里云上转过来的 安装证书 Tomcat支持JKS格式证书,从Tomcat7开始也支持PFX格式证书,两种证书格式任选其一。 文件说明: 1. 证书文件1539490276504.pem,包含两段内容,请不要删除...

wangyanbao
2018/10/18
286
0
已备案的域名和tomcat的J2EE项目做的网站相关联步骤

材料:已到工信部备案好了的域名 服务器ip J2EE开发好了的网站 域名要先解析,这在网络上有很多方法,很容易就搜到。 如:http://jingyan.baidu.com/article/ad310e8086aebf1849f49e94.html就...

houss2012
2018/06/26
0
0
Tomcat8源码分析3--Bootstrap启动过程

执行Bootstrap类的static代码块, 初始化Bootstrap的catalinaHomeFile属性和catalinaBaseFile属性, 默认情况下值都为tomcat的安装目录. 关于这两个属性, 说明如下. =========================...

德胜
2014/11/25
1K
0
Tomcat源码解读系列——Tomcat的核心组成和启动过程

声明:源码版本为Tomcat 6.0.35 前面的文章中介绍了Tomcat的基本配置,每个配置项也基本上对应了Tomcat的组件结构,如果要用一张图来形象展现一下Tomcat组成的话,整个Tomcat的组成可以如下图...

leamon
2014/03/20
4.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部