Tomcat整体架构(Tomcat源码阅读系列之二)

来源:互联网 发布:c语言根号下分数 编辑:程序博客网 时间:2024/04/26 07:53

  • 前言
  • Tomcat的总体架构
  • Server分析
  • Service分析
  • Connector分析
  • Engine分析
  • Host分析
  • Context分析
  • Value
  • Wrapper
  • 小结

前言

本文章是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:Tomcat源码分析环境搭建 一文中介绍了如何在Eclipse中运行Tomcat源代码,本文将介绍一下Tomcat的总体架构体系。

Tomcat的总体架构

Tomcat既是一个Http服务器也是一个Servlet容器,其总体架构如下:

Tomcat总体架构

从上图我们可以看出Tomcat主要涉及的组件有:
- Server
- Service
- Connector
- Container
- Engine
- Host
- Context
相信查看或配置过conf/server.xml文件的同学都对以上的组件有种似曾相识的感觉,没错,conf/server.xml文件中就包含了以上组件的配置,或许细心的同学会问,那ProtocolHandler、Endpoint等这些是什么呢?它们不算是Tomcat的组件吗?它们是Connector组件的结构组件,也属于Tomcat的组件,只是它们用于实现Connector组件的,因而没有把它们都列为Tomcat的组件。conf/server.xml文件内容如下(省略了Tomcat默认注释的部分,详细的可自行打开server.xml文件进行查看):

<?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.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分析

Server是Tomcat最顶层的容器,代表着整个服务器,即一个Tomcat只有一个Server,Server中包含至少一个Service组件,用于提供具体服务。在Tomcat源码中Server组件对应源码中的org.apache.catalina.core.StandardServer类,其继承结构类图如下:
StandardServer继承结构类图

或许好问的同学会忍不住提问,StandardServer为什么要继承LifecycleMBeanBase类和实现Server接口呢?对于这两个问题我是这样理解的,在Tomcat中StandardServer实现Server接口,在使用时调用模块不直接依赖StandardServer,而是依赖于Server,体现依赖倒置(DIP)的设计原则,让模块间的依赖通过抽象实现,实现类之间不发生直接的依赖关系,而是通过接口来产生;而继承LifecycleMBean类与Tomcat生命周期的管理方式有关,详情在以后的文章中进行说明。

Service分析

接下来我们看Service组件,是Server层(对应Server组件)中的一个逻辑功能层,在conf/server.xml文件中,我们可以看到Service组件包含了Connector组件和Engine组件,即Service相当于Connector和Engine组件的包装器,将一个或者多个Connector和一个Engine建立关联关系。在默认的配置文件中,定义了一个叫Catalina 的服务,它将HTTP/1.1和AJP/1.3这两个Connector与一个名为Catalina 的Engine关联起来。

Connector分析

对于Connector组件,它主要是用于处理连接相关的事情,并提供Socket与request、response的转换;如Tomcat是http服务器,提供http服务,而我们知道Http应用协议最终需要TCP层协议进行包的传递,而对应Tomcat中则是通过Socket进行通信。一个Connector会监听一个独立的端口来处理来自客户端的请求。下面我们对server.xml默认配置的两个Connector进行说明。
- HTTP/1.1,<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />,它监听端口8080,这个端口值我们可以根据实际情况进行修改,connectionTimeout定义了连接超时时间,单位是毫秒,redirectPort 定义了ssl的重定向接口,根据上述配置,Connector会将ssl请求转发到8443端口。
- AJP/1.3,<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />, AJP表示Apache Jserv Protocol,此连接器将处理Tomcat和Apache http服务器之间的交互,此连接器用于处理我们将Tomcat和Apache http服务器结合使用的情况,如在同一台物理Server上部署一个Apache http服务器和多台Tomcat服务器,通过Apache服务器来处理静态资源以及负载均衡时,针对不同的Tomcat实例需要AJP监听不同的端口。Connector对应源代码中的org.apache.catalina.connector.Connector,其继承结构如下:
Connector继承结构

Engine分析

Engine,用于管理多个站点,一个Service最多只能有一个Engine,而一个Engine可以包含一个或者多个Host,即一个Tomcat实例可以配置多个虚拟主机,默认的情况下 conf/server.xml 配置文件中<Engine name="Catalina" defaultHost="localhost"> 定义了一个名为Catalina的Engine,Engine对应Tomcat源码中的org.apache.catalina.core.StandardEngine,其继承结构关系图如下:
StandardEngine继承结构图

Host分析

Host,代表一个站点,也可以叫虚拟主机,一个Host可以配置多个Context,在server.xml文件中的默认配置为<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">, 其中appBase=webapps, 也就是<CATALINA_HOME>\webapps目录,unpackingWARS=true 属性指定在appBase指定的目录中的war包都自动的解压,autoDeploy=true 属性指定对加入到appBase目录的war包进行自动的部署。在Tomcat源代码中对应org.apache.catalina.core.StandardHost, 其继承结构关系如下图:
StandardHost继承结构关系

Context分析

Context,代表一个应用程序,对应平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件,换句话说每一个运行的webapp最终都是以Context的形式存在,每个Context都有一个根路径和请求路径;与Host的区别是Context代表一个应用,如,默认配置下webapps下的每个目录都是一个应用,其中ROOT目录中存放主应用,其他目录存放别的子应用,而整个webapps是一个站点。Context对应源代码中的org.apache.catalina.core.StandardContext, 其继承结构如下:
StandardContext继承结构

在Tomcat中通常采用如下方式创建一个Context
1. 在<CATALINA_HOME>\webapps 目录中创建一个目录,此时将自动创建一个context,默认context的访问url为http://host:port/dirname,也可以通过在ContextRoot\META-INF 中创建一个context.xml文件,其中包含如下内容来指定应用的访问路径:<context path="/urlpath">
2. 在server.xml文件中增加context 元素,如下:

  <Context path="/urlpath" docBase="/test/xxx" reloadable=true></Context> </Host></Engine>

这样我们就可以通过http://host:port/urlpath访问上面配置的应用。

Value

对于这个组件Tomcat整体架构图中并没有指出,是因为它是Container用于处理请求的,是Tomcat中责任链模式的实现,责任链模式是指在一个请求处理的过程中有多个处理者依次对请求进行处理,每个处理者负责自己相应的处理,处理完毕后将处理后的请求返回,再让下一个处理者继续处理。但是Tomcat的Value的管道模型和普通的责任链模式有点不同,主要有两点:
1. 每个Container容器,都有特定的Value,而且是在管道的最后一个执行,叫做BaseValue,是不可删除的
2. 在上层容器的管道的BaseValue中会调用下层容器的管道

Tomcat 默认定义了一个名为org.apache.catalina.valves.AccessLogValve的Valve,这个Valve负责拦截每个请求,然后记录一条访问日志。

Wrapper

每个Wrapper封装着一个Servlet,其对应Tomcat源码中的org.apache.catalina.core.StandardWrapper,其继承结构类图与StandardContext、StandardHost类似,在此不再阐述。

小结

Server是Tomcat最顶层的容器,代表着整个服务器,一个Tomcat只有一个Server,Server中包含至少一个Service组件,而Service主要包含两部分:Connector和Container,Connector用于处理连接相关的事情,并提供Socket与Request和Response的转换,Container用于封装和管理Servlet,以及具体处理request请求。

[注:以上为阅读Tomcat源码时所做的小结,可能存在错误的地方,如有发现,欢迎email或者留言指明交流,Email地址:woodyoilovecn@gmail.com]

0 0
原创粉丝点击