Java服务容器——Tomcat


发布于 2016-05-08 / 47 阅读 / 0 评论 /
Tomcat是免费开源,轻量级应用服务器。

1.Tomcat概述

Tomcat是免费开源,轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。实际上Tomcat 部分是Apache 服务器的扩展,但它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。只实现了JSP/Servlet的相关规范,不支持EJB。虽说是tomcat服务器,但是并不是真正的硬件,它是部署在电脑上的软件服务。

Tomcat具有双重身份:HTTP服务器、Servlet容器。

2.tomcat架构

tomcat的架构如下图所示:

Tomcat的核心功能有:处理socket连接,负责将网络字节流与Request和Response对象的转化;加载和管理Servlet,以及具体处理Request请求。

Tomcat支持的IO模型有NIO、NIO2、APR。Tomcat支持的应用层协议有http1.1、ajp、http2.0。

Tomcat最顶层是Server,一个Server有多个Service,一个Service有多个连接器和容器,连接器和容器之间通过ServletRequest和ServletResponse通信。

Tomcat引用层协议支持一下三种:

应用层协议

描述

HTTP/1.1

大部分web应用采用的访问协议,也是默认协议

AJP

用于和WX集成(如Apache),实现对静态资源的优化以及集群部署,当前支持AJP/1.3

HTTP/2

HTTP2.0大幅度地提升了web性能,下一代HTTP协议,自8.5以及9.0版本之后支持

针对具体协议的处理能力,Tomcat按照协议和IO提供了6个实现类:AjpNIOProtocol、AjpAprProtocol、AjpNio2Protocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol。

Tomcat传输层协议支持以下三种:

传输层协议

描述

NIO

非阻塞I/O,采用java NIO类库实现

NIO2

异步IO,采用JDK7最新的NIO2类库实现

APR

采用Apache可移植运行库实现,是C/C++编写的本地库,如果选择该方案,需要单独安装APR库。

8.0之前的Tomcat的默认IO方式为BIO,8.0之后为NIO,性能要优于BIO,APR是本地库,性能最佳,但是需要操作系统底层支持,要安装可移植库。

架构中包含以下七个部分。

2.1.startup.sh

Tomcat的启动脚本,启动JVM,启动类为Bootstrap。

2.2.Bootstrap

启动类,负责初始化类加载器,并实例化Catalina。

2.3.Catalina

也是启动类,负责解析server.xml,并创建Server组件。

2.4.Server

负责启动Service组件。

2.5.Service

负责启动容器和连接器组件。

2.6.Connector——连接器

连接器需要实现的功能有:

(1)监听网络端口

(2)接收网络请求

(3)读取网络字节流

(4)根据应用层协议解析字节流,生成统一的tomcat request和tomcat response对象

(5)将tomcat request对象转成ServletRequest

(6)调用servlet容器,得到ServletResponse

(7)将ServletResponse转成tomcat response

(8)将tomcat response转成网络字节流

(9)将response字节流通过网络写回客户端

以上功能可以概括为三点:网络通信;应用层协议解析;tomcat request/response与servlet request/response的转换。

Endpoint 负责提供字节流给 Processor,Processor 负责提供 tomcat request 对象给 Adapter,Adapter负责提供 Servlet Request 给容器。

其中 Endpoint 和 Processor 抽象组装在一起形成了 ProtocolHandler 组件。

2.6.1.Endpoint

Endpoint是对传输层协议的抽象。

接口,抽象实现类是 AbstractEndpoint,具体子类在 NioEndpoint 和 Nio2Endpoint,其中两个重要组件:Acceptor 和 SocketProcessor。

Acceptor 用于监听 Socket 连接请求,SocketProcessor 用于处理收到的 Socket 请求,提交到线程池 Executor 处理。

2.6.2.Processor

Processor是对应用层协议的抽象。

接收 Endpoint 的 socket,读取字节流解析成 tomcat request 和 response,通过 adapter 将其提交到容器处理。Processor 的具体实现类 AjpProcessor、Http11Processor 实现了特定协议的解析方法和请求处理方式。

Endpoint 接收到 socket 连接后,生成一个 socketProcessor 交给线程池处理,run 方法会调用 Processor 解析应用层协议,生成 tomcat request 后,调用 adapter 的 service 方法。

2.6.3.Adapter

ProtocolHandler 接口负责解析请求生成 tomcat request,CoyoteAdapter 的 service 方法,将 Tomcat Request 对象,转成 ServletRequest,再调用 service 方法。

2.7.Engine——容器

容器内部具有以下父子关系的组件:Engine、Host、Context、Wrapper 和 Servlet。

2.7.1.容器内部组件结构

Host 代表的是一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序。Context 表示 web 应用程序、wrapper 表示 servlet、context 有多个 wrapper,host 也有多个 context。父子关系和映射关系如下图所示:

下面通过一个实例来说明各个概念之间的关系。

Engine 表示引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine。

2.7.2.容器内部调用链

容器通过 Pipeline-Valve 责任链,对请求一次处理,invoke 处理方法,每个容器都有一个 Pipeline,触发第一个 Valve,这个容器的 valve 都会被调到,不同容器之间通过 Pipeline 的 getBasic 方法,负责调用下层容器的第一个 Valve。如下图所示:

整个调用连由连接器中的 adapter 触发,调用 engine 中的第一个 Valve。

connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

ServletContext 是 tomcat 中的一个成员变量,spring 中的 ApplicationContext 是 servlet 规范中的 ServletContext 属性。

3.Spring-Boot集成tomcat

SpringBoot框架中,使用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内嵌式的Tomcat。通过以下依赖,就可以自动加入tomcat。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

有的公司在生产环境不使用springboot自带的tomcat,则需要在代码中进行排除。配置如下所示:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>