tomcat-架构原理   整体架构 组件 启动流程 机制

Apache Tomcat,通常称为Tomcat服务器,是一个开源的java servlet容器由Apache软件基金会(ASF)开发。Tomcat实现了几个java EE规范包括java servlet和JavaServer Pages(JSP),java EL和WebSocket,并提供了一个“纯java”HTTP Web服务器环境中的java代码可以运行。

整体架构

tomcat-架构原理
 
整体架构
组件
启动流程
机制

tomcat-架构原理
 
整体架构
组件
启动流程
机制

组件

tomcat-架构原理
 
整体架构
组件
启动流程
机制

tomcat-架构原理
 
整体架构
组件
启动流程
机制

以下说明以tomcat 8.0 版本为前提

Catalina

Calalina是Tomcat的servlet容器。Calalina实现了Sun MyStand对Servlet和JavaServer页面(JSP)的规范。在Tomcat中,领域元素表示分配给这些用户的用户名、密码和角色(类似于UNIX组)的“数据库”。领域的不同实现允许Calalina集成到已经创建和维护这样的认证信息的环境中,然后使用servlet规范中描述的信息来实现容器管理的安全性。

Server

Server:服务器的意思,代表整个tomcat服务器,一个tomcat只有一个Server; 
Server是Tomcat最顶层的容器,代表着整个服务器,即一个Tomcat只有一个Server,Server中包含至少一个Service组件,用于提供具体服务。这个在配置文件中也得到很好的体现(port=”8005” shutdown=”SHUTDOWN”是在8005端口监听到”SHUTDOWN”命令,服务器就会停止)。

service 
Service:Server中的一个逻辑功能层, 一个Server可以包含多个Service;

接收客户端的请求,然后解析请求,完成相应的业务逻辑,然后把处理后的结果返回给客户端,一般会提供两个节本方法,一个start打开服务Socket连接,监听服务端口,一个stop停止服务释放网络资源。

Connector 
称作连接器,是Service的核心组件之一,一个Service可以有多个Connector,主要是连接客户端请求; 
用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端。

一个Connector会监听一个独立的端口来处理来自客户端的请求。server.xml默认配置了两个Connector: 
,它监听端口8080,这个端口值可以修改,connectionTimeout定义了连接超时时间,单位是毫秒,redirectPort 定义了ssl的重定向接口,根据上述配置,Connector会将ssl请求转发到8443端口。 
, AJP表示Apache Jserv Protocol,它将处理Tomcat和Apache http服务器之间的交互,此连接器用于处理我们将Tomcat和Apache http服务器结合使用的情况,如在同一台物理Server上部署一个Apache http服务器和多台Tomcat服务器,通过Apache服务器来处理静态资源以及负载均衡时,针对不同的Tomcat实例需要AJP监听不同的端口。 
Connector使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的(tomcat9已经删除了这个类,不再采用BIO的方式),Http11NioProtocol使用的是NioSocket来连接的。

其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。 
1. Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request(这个Request和ServletRequest无关),Adapter充当适配器,用于将Request转换为ServletRequest交给Container进行具体的处理。 
2. Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。 
3. Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。

Container

Service的另一个核心组件,按照层级有Engine,Host,Context,Wrapper四种,一个Service只有一个Engine,其主要作用是执行业务逻辑;

但如果将请求监听和请求处理放在一起,扩展性会变差,毕竟网络协议不止HTTP一种,如果想适配多种网络协议,请求处理又相同,这时就无能为力了,tomcat的设计大师不会采取这种做法,而是将请求监听和请求处理分开为两个模块,分别是Connector和Container,Connector负责处理请求监听,Container负责处理请求处理。

但显然tomcat可以有多个Connector,同时Container也可以有多个。那这就存在一个问题,哪个Connector对应哪个Container,提供复杂的映射吗?相信看过server.xml文件的人已经知道了tomcat是怎么处理的了。

没错,Service就是这样来的。在conf/server.xml文件中,可以看到Service组件包含了Connector组件和Engine组件(前面有提过,Engine就是一种容器),即Service相当于Connector和Engine组件的包装器,将一个或者多个Connector和一个Engine建立关联关系。在默认的配置文件中,定义了一个叫Catalina 的服务,它将HTTP/1.1和AJP/1.3这两个Connector与一个名为Catalina 的Engine关联起来。

一个Server可以包含多个Service(它们相互独立,只是公用一个JVM及类库),一个Service负责维护多个Connector和一个Container。

tomcat-架构原理
 
整体架构
组件
启动流程
机制

Engine 
一个Service中有多个Connector和一个Engine,Engine表示整个Servlet引擎,一个Engine下面可以包含一个或者多个Host,即一个Tomcat实例可以配置多个虚拟主机,默认的情况下 conf/server.xml 配置文件中 定义了一个名为Catalina的Engine。

Host 
Host,代表一个站点,也可以叫虚拟主机,一个Host可以配置多个Context,在server.xml文件中的默认配置为, 其中appBase=webapps, 也就是webapps目录,unpackingWARS=true 属性指定在appBase指定的目录中的war包都自动的解压,autoDeploy=true 属性指定对加入到appBase目录的war包进行自动的部署。

一个Engine包含多个Host的设计,使得一个服务器实例可以承担多个域名的服务,是很灵活的设计。

Context

Context,代表一个应用程序,就是日常开发中的web程序,或者一个WEB-INF目录以及下面的web.xml文件,换句话说每一个运行的webapp最终都是以Context的形式存在,每个Context都有一个根路径和请求路径;与Host的区别是Context代表一个应用,如,默认配置下webapps下的每个目录都是一个应用,其中ROOT目录中存放主应用,其他目录存放别的子应用,而整个webapps是一个站点。

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

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

Wrapper

一个Context可以包含多个Servlet处理不同请求,当然现在的SpringMVC,struts框架的出现导致程序中不再是大量的Servlet,但其实本质是没变的,都是由Servlet来处理或者当作入口。

在tomcat中Servlet被称为wrapper,其标准类图如下:

那么为什么要用Wrapper来表示Servlet?这和tomcat的处理机制有关,为了更加灵活,便于扩展,tomcat是用管道(pipeline)和阀(valve)的形式来处理请求,所以将Servlet丢给Wrapper。这个后续再分析。

那么现在tomcat就是这样的:

Coyote 
CyoOt是Tomcat的一个连接器组件,支持ajp、http1.1、spdy三种协议。

1、http 
默认情况下,HTTP连接器使用Tomcat进行安装,并准备使用。该连接器具有最低的等待时间和最佳的整体性能。 
对于集群,必须安装支持Web会话粘性的HTTP负载平衡器,以将流量引导到Tomcat服务器。Tomcat支持Adache HTTP Server 2 .x上的MODJOXER代理,并在默认情况下包含在Apache HTTP服务器2.2中作为负载均衡器。应该注意的是,HTTP代理的性能通常低于AJP的性能,所以AJP聚类通常是优选的。

2、ajp 
当使用单个服务器时,在Tomcat实例前面使用 native webserver时的性能大部分时间都比具有默认HTTP连接器的独立Tomcat更差,即使Web应用程序的很大一部分是由静态文件构成的。如果出于任何原因需要与本机WebServer集成,AJP连接器将提供比代理HTTP更快的性能。从Tomcat的角度来看,AJP聚类是最有效的。它在功能上等同于HTTP集群。

此Tomcat版本支持的本机连接器为:

JK 1.2 .x与任何支持的服务器

Apache HTTP Server 2 .x(默认情况下包含在Apache HTTP服务器2.2中)的MODY代理,启用了AJP

3、spdy 
还有对SPDY协议的支持,尽管SPDY还不够完善。

Jasper 
Tomcat的JSP引擎。解析JSP文件编译成java代码的servlet(可以处理卡特琳娜)。在运行时,Jasper检测到对JSP文件的更改并重新编译它们。

在版本5中,Tomcat使用JasPar 2,它是Sun MyStices的JSP 2规范的一个实现。从Jasper到Jasper2,增加了重要的特征:

JSP标记库池——JSP文件中的每个标记标记由标记处理程序类处理。可以在整个JSP servlet中汇集并重用标记处理程序类对象。 
背景JSP编译,编译修改JSP java代码,旧的版本仍然是可用的服务器的请求。旧JSP servlet一旦新的JSP servlet完成重新编译就被删除。 
在包含页面更改时重新编译JSP——可以在运行时插入页面并将其包含到JSP中。JSP不仅可以用JSP文件更改重新编译,而且还可以包含页面更改。 
java编译器JDT -Jasper2可以使用Eclipse JDT(java开发工具)而不是蚂蚁和java编译器javac。 
添加三个新的组分,释放Tomcat 7:

Cluster 
This component has been added to manage large applications. It is used for load balancing that can be achieved through many techniques. Clustering support currently requires the JDK version 1.5 or higher.

High availability 
A high-availability feature has been added to facilitate the scheduling of system upgrades (e.g. new releases, change requests) without affecting the live environment. This is done by dispatching live traffic requests to a temporary server on a different port while the main server is upgraded on the main port. It is very useful in handling user requests on high-traffic web applications.[6]

Web application 
It has also added user- as well as system-based web applications enhancement to add support for deployment across the variety of environments. It also tries to manage sessions as well as applications across the network.

Tomcat is building additional components. A number of additional components may be used with Apache Tomcat. These components may be built by users should they need them or they can be downloaded from one of the mirrors.[7]

启动流程

tomcat的启动流程很标准化,入口是BootStrap,统一按照生命周期管理接口Lifecycle的定义进行启动。首先,调用init()方法逐级初始化,接着调用start()方法进行启动,同时,每次调用伴随着生命周期状态变更事件的触发。

每一级组件除完成自身的处理外,还有负责调用子组件的相关调用,组件和组件之间是松耦合的,可以通过配置进行修改。

大致流程图如下:

tomcat-架构原理
 
整体架构
组件
启动流程
机制

机制

生命周期

tomcat为所有的组件都提供了生命周期管理,继承LifecycleMBeanBase则跟tomcat中的生命周期机制有关。

参考资料

https://tomcat.apache.org/tomcat-8.5-doc/default-servlet.html

https://blog.csdn.net/w1992wishes/article/details/79242797