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引用层协议支持一下三种:
针对具体协议的处理能力,Tomcat按照协议和IO提供了6个实现类:AjpNIOProtocol、AjpAprProtocol、AjpNio2Protocol、Http11NioProtocol、Http11Nio2Protocol、Http11AprProtocol。
Tomcat传输层协议支持以下三种:
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>