Tomcat我们都知道是一个开源的、实现了大部分Java EE、Servlet、JSP规范的Servlet容器, 允许我们将实现了Serlvet接口的Web程序war包进行部署运行。 但是你有对Tomcat做过细致的学习么? 我相信大部分同学和我一样,之前也是只会进行简单使用,如启动、停止、部署Web应用程序等, 对其工作原理和组件架构没有深入去学习。 趁着机会,我们一起深入学习Tomcat组件架构和数据流向。
除了开源版本的Servlet容器: Tomcat, 我们也还听到或者使用过一些闭源商业的Servlet容器/应用服务器, 例如Oracle的WebLogic、IBM的WebSphere等。
Tomcat的组件之间是存在层次结构的:
1、首先整个Tomcat我们称为一个Server, 这个Server就是Tomcat, 有且只有1个
2、一个Server可以存在多个Service, 每个Service必须存在一个【Connector连接器组件(Coyote框架)】或者多个Connector连接器、有且只有1个【Container组件(Catalina)】
3、Container组件(Catalina)存在一个Engine组件, Engine组件存在多个Host虚拟主机
4、每个Host虚拟主机又存在多个Context, 一个Context可以认为就是一个Web应用
5、每个Context又存在多个Warpper, 一个Warpper包含一个Servlet类
Connector连接器组件,默认使用Coyote框架实现。 Connector连接器是Tomcat构成的两大组件之一。
Connector本质上就是针对一些应用层协议进行管理以及解析相关工作的组件, 例如单纯处理HTTP1.1协议的解析、响应等相关工作,可以理解这个组件就是Tomcat内置了HTTP服务器要实现的功能,和Nginx的作用类似。 根据单一职责原则,Connector只处理与HTTP协议相关的工作内容, 之后将HTTP协议请求的Request对象转换为下一个组件Container Servlet容器所需要的ServletRequest对象, 后续业务逻辑的内容交给了Container组件进行实际业务处理,最后返回Response响应对象。
Container容器组件,默认使用Catalina框架实现。 Container容器是Tomcat构成的另外一个重要组件。
Container容器组件是整个Tomcat的核心组件,名为Catalina容器。 从启动脚本catalina.sh这些命名,足以彰显和整个Tomcat关系。 Container负责对Servlet对象进行生命周期管理、如初始化、调用doService方法、销毁、通过mapping URL映射找到对应的Servlet对象进行执行等等, 最后将Response信息返回给Connector连接器组件。
例如浏览器访问http://localhost:8080/myapp/路径,此时会经历以下流程:
1、Connector的Endpoint子组件监听8080端口,接收客户端浏览器请求报文(TCP/Socket)
2、经过Processor子组件处理,解析为应用层协议HTTP协议,将请求信息拿到进行封装为Request对象
3、由于Container组件需要的是ServletRequest对象,直接传递Connector的Request对象,对方无法处理,所以通过子组件Adapter进行适配器转换,将Request对象转换为ServletRequest对象
4、Container拿到请求数据,根据请求的域名查找对应的Host虚拟主机进行处理
5、根据url找到对应Context应用为myapp, 查找myapp/WEB-INFO/web.xml,根据web.xml的mapping映射关系定位到对应的Servlet
6、定位到具体Servlet,根据请求方法get或者post调用对应doGet、doPost方法,最后返回ServletResponse对象给Connector
7、Connector连接器拿到ServletResponse对象通过子组件Adapter转换为Response对象,最后将响应请求的内容返回给浏览器客户端
Tomcat本质就是一个Java进程,Java进程自然就是一个JVM虚拟机, 那就是对JVM的一些参数调优.
例如-Xmx、-Xms等
GC垃圾回收器算法, 例如CMS、G1、Serinal等等
maxConnections、maxThreads、acceptCount