Tomcat系统架构与原理剖析
浏览器处理服务器的流程
Tomcat系统总体架构
Tomcat请求处理大概流程
Tomcat有两个身份:
- Tomcat是一个http容器
- Tomcat还是一个Servlet容器
Tomcat Servlet容器处理流程
当用户请求某个URL资源时
1) HTTP服务器会把请求信息使用ServletRequest对象封装起来
2) 进一步去调用Servlet容器中某个具体的Servlet
3) 在2)中,Servlet容器拿到请求后,根据URL和servlet的映射关系,找到对应的Servlet
4) 如果Servlet还没有被加载,就用反射机制创建这个Servlet,并调用Servlet的init方法来完成初始化
5) 接着调用这个具体的Servlet的ervice方法去处理请求,请求处理结果使用ServletResponse对象封装
6) 把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端Tomcat总体架构综述
Tomcat有两个非常重要的功能需要完成
1) 和客户端浏览器进行交互,进行socket通信,将字节流和Request/Response等对象进行转换
2) Servlet容器处理业务逻辑
Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来完成Tomcat的两大核心功能。 - 连接器,负责对外交流: 处理Socket连接,负责网络字节流和Request和Responese对象的转化;
- 容器,负责内部处理:加载和管理Servlet,以及具体处理Request请求;
Tomcat连接器组件Coyote
Coyote简介
Coyote是Tomcat中连接器的组件名称,是对外的接口。客户端通过Coyote与服务器建立连接、发送请求并接受响应
- Coyote封装了底层的网络通信(Socket请求及响应处理)
- Coyote使Catalina容器与具体的请求协议以及IO操作方式完全解耦
- Coyote将Socket输入转换封装为Request对象,进一步封装后交由Catalina容器进行处理,处理请求完成后,Catalina通过Coyote提供的Response对象将结果写入输出流
- Coyote负责的是具体协议(应用层)和IO(传输层)相关内容
Tomcat Coyote支持的I/O模型与协议,Tomcat支持多种应用程序协议和I/O模型,如下:
应用层协议: - HTTP/1.1 , 这是大部分web应用采用的访问协议
- AJP 用于和WX集成(Apache),以实现对静态资源的优化以及集群部署,当前支持AJP/1.3
- HTTP/2 Http 2.0 大幅度的提升了Web性能。下一代HTTP协议,自8.5以及9.0版本之后支持
IO模型: - NIO 非阻塞I/o 采用java NIO 类库实现
- NIO2 异步I/O 采用JDK7最新的NIO2类库实现
- APR 采用Apcahe可移植运行库实现,是C/C++编写的本地库,如果选择该方案,需要单独安装APR库
在8.0之前,Tomcat默认采用的I/O方式为BIO,之后改为了NIO。无论是NIO、NIO2还是APR,在性能方面均优于以往的BIo。如果采用APR,甚至可以达到Apache HTTP Server的性能。
Coyote的内部组件及流程
- Coyote组件及其作用
组件 作用描述 Endpoint EndPoint是Coyote通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint用来实现TCP/IP协议的
|Processor|Processor是Coyote协议处理接口,如果说endPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议的,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交给容器处理,Processor是对应应用层协议的抽象|
|ProtocolHandler|Coyote协议接口,通过EndPint和Processor,实现针对具体协议的处理能力。Tomcat按照协议和I/O提供的六个实现类:AjpNioProtocol,AjpAprProtocol,AjpNio2Protocol,Http11NioProtocol,Http11Nio2Protocol,Http11AprProtocol|
|Adapter|由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类来封装这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入了CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdpater的Service方法,传入的是Tomcat Request对象。CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器|
Tomcat Servlet容器 Catalina
Tomcat模块分层结构图及Catalina位置
Tomcat是一个由一系列可配置(conf/server.xml)的组件构成的web容器,而Catalina是Tomcat的Servlet容器。
从另一个角度来说,Tomcat本质上就是一款Servlet容器,因此Catalina才是Tomcat的核心,其他模块都是Catalina提供支撑的。比如:通过Coyote模块提供链接通信,Jasper模块提供JSP引擎,Naming提供命名服务,Juli提供日志服务。
Servlet容器Catalina的结构
其实,可以认为整个Tomcat就是一个Catalina实例,Tomcat启动的时候会初始化这个实例,Catalina实例通过加载server.xml完成其他实例的创建,创建并管理server,Server创建并管理多个服务,每个服务又可以有多个Connector和一个Container。一个Catalina实例对应一个Server实例,一个server实例对应多个Service实例,每一个service实例下可以有多个Connector实例和一个Container实例。
- Catalina:负责解析Tomcat的配置文件(server.xml),以此来创建服务器Server组件并管理
- Server:服务器表示整个Catalina Servlet容器以及其他组件,负责组装并启动Servlet引擎,Tomcat连接器。Server通过实现Lifecycle接口,提供一种优雅的启动和关闭整个系统的方式
- Service:服务是Server内部的组件,一个Server包含多个Service。它将若干个Connector组件绑定到一个Container
- Container:容器,负责处理用户的servlet请求,并返回对象给web用户的模块
Container组件的具体结构
Container组件有几种具体的组件,分别是Engine、Host、Context和Wrapper。这四种组件(容器)是父子关系。Tomcat通过一种分层的架构,使得Servlet容器具有很好的灵活性。
- Engine:表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个service最多只能有一个Engine,但是一个引擎可包含多个Host
- Host:标识一个虚拟足迹,或者说一个站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可包含多个Context
- Context:标识一个web应用程序,一个web应用可包含多个Wrapper
- Wrapper:表示一个Servlet,Wrapper作为容器中的最底层,不能包含子容器
这些关系的配置其实就体现在conf/server.xml中
Tomcat服务器核心配置详解
主要标签结构如下:
<!-- |
Server标签
<!-- |
Service标签
<!-- |
Executor标签
Executor标签主要是创建一个线程池,当Connector监听到端口的消息时,可以从Executor线程池中那到线程去处理。
<!-- |
Connector标签
Connector标签用于创建链接器实例
默认情况下,server.xml配置了两个链接器,一个支持HTTP协议,一个支持AJP协议
大多数情况下,我们并不需要新增链接器配置,只需要根据对已有的链接器进行优化
<!-- |
Engine标签
Engine表示Servlet引擎
<!-- |
Host标签
Host标签用于配置一个虚拟主机
<!-- |
Context标签
Context标签用于配置一个web应用
<Host name="localhost" appBase="webapps" unpackWARs = "true" autoDeploy = "true"> |