Tomcat工作原理介绍

Web应用程序都是靠Web服务器运行的,Tomcat是常用的Web服务器(兼具Servlet容器+HTTP服务器功能)之一,此篇博客将从工作原理上来认识Tomcat。Tomcat作为Web服务器需要处理两类核心任务:处理 Socket 连接,负责网络字节流与Request和Response对象的转化。加载和管理 Servlet,以及处理 Request 请求。为了处理这两类任务,Tomcat 设计了两个核心组件连接器Connector和容器Container来分别做这两件事情。连接器负责对外交流,容器负责内部处理。

Tomcat工作原理介绍_第1张图片

连接器对Servlet 容器屏蔽了协议及 I/O 模型等的区别,无论是 HTTP 还是 AJP,在容器中获取到的都是一个标准的 ServletRequest 对象。连接器主要完成的任务如下所示:

监听网络端口。
接受网络连接请求。
读取请求网络字节流。
根据具体应用层协议(HTTP/AJP)解析字节流,生成统一的 Tomcat Request 对象。
将 Tomcat Request 对象转成标准的 ServletRequest。
调用Servlet 容器,得到 ServletResponse。
将ServletResponse 转成 Tomcat Response 对象。
将Tomcat Response 转成网络字节流。
将响应字节流写回给浏览器。

容器部分,Tomcat设计了4种容器,分别是 Engine、Host、Context 和 Wrapper。这 4 种容器不是平行关系,而是父子关系。四种容器的关系如下图所示:

Tomcat工作原理介绍_第2张图片

Context表示一个Web应用程序;Wrapper表示一个Servlet,一个Web应用程序中可能会有多个Servlet;Host代表的是一个虚拟主机,或者说一个站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机下可以部署多个Web应用程序;Engine 表示引擎,用来管理多个虚拟站点,一个 Service最多只能有一个Engine。查看tomcat下server.xml的配置,可以看到有关于service/engine/connector/Host等的配置。在server.xml中可以配置多个Connector,不同的Connector对应不用的协议连接,例如https默认在8080端口,https默认在8443接口。

Tomcat工作原理介绍_第3张图片Tomcat工作原理介绍_第4张图片

在Tomcat目录的webapps下,可以创建多个目录放入多个应用的war包,这样一个Tomcat就可以部署多个web应用了。

当在浏览器中访问一个地址“http://localhost:8080/one/hello-servlet”,Tomcat是如何定位到Servlet的呢?首先,根据协议和端口号选定 Service 和 Engine。Tomcat 的每个连接器都监听不同的端口,比如 Tomcat 默认的 HTTP 连接器监听 8080 端口、默认的 AJP 连接器监听 8009 端口。上面例子中的 URL 访问的是 8080 端口,因此这个请求会被 HTTP 连接器接收,而一个连接器是属于一个 Service 组件的,这样 Service 组件就确定了。另外Service 组件里除了有多个连接器,还有一个容器组件,具体来说就是一个 Engine 容器,因此 Service 确定了也就意味着 Engine 也确定了。然后,根据域名选定 Host。Service 和 Engine 确定后,Mapper 组件通过 URL 中的域名去查找相应的 Host 容器,比如例子中的 URL 访问的域名是 localhost,因此 Mapper 会找到localhost对应的这个容器。之后,根据 URL 路径找到 Context 组件。Host 确定以后,Mapper 根据 URL 的路径来匹配相应的 Web 应用的路径,比如例子中访问的是 one/hello-servlet,因此找到了对应的one这个Context 容器。最后,根据 URL 路径找到 Wrapper(Servlet)。Context 确定后,Mapper 再根据 web.xml 中配置的 Servlet 映射路径来找到具体的 Wrapper 和 Servlet。

前面介绍了Tomcat中的连接器和容器,接着再来看看Tomcat服务启动过程,下载Tomcat解压后,进入bin目录,执行startup和shutdown脚本即可实现tomcat的启动和停止。Tomcat启动过程如下图所示:

Tomcat工作原理介绍_第5张图片

1.Tomcat 本质上是一个 Java 程序,因此 startup.sh 脚本会启动一个JVM 来运行Tomcat 的启动类 Bootstrap。

2.Bootstrap 的主要任务是初始化Tomcat 的类加载器,并且创建Catalina。

3.Catalina是一个启动类,它解析server.xml、创建相应的组件,并调用Server的start方法。

4.Server组件的职责就是管理Service组件,它会负责调用Service的start方法。

5.Service组件的职责是管理连接器和顶层容器Engine,因此它会调用连接器和Engine的start方法

查看Tomcat包下面的startup.sh脚本,可以看到实际调用的是catalina.sh,该脚本会运行Bootstrap的jar包,如果有些环境变量需要设置,可以在setenv.sh文件下设置,如下图所示启动CAT(一个链路追踪工具)时,在setenv.sh中设置了环境变量,启动Tomcat的时候也可以看到添加的环境变量生效。

Tomcat工作原理介绍_第6张图片

前面介绍的都是Tomcat作为独立的部分来部署web应用,实际Springboot已经内部集成了tomcat作为web服务器,启动一个springboot的应用,启动日志如下所示:可以看到启动过程中启动了内置的tomcat,这样当springboot程序启动完成后,可以在浏览器或者postman上调用封装的接口。

Tomcat工作原理介绍_第7张图片

在Tomcat独立部署的模式下,我们通过startup脚本来启动Tomcat,Tomcat中的Bootstrap和Catalina会负责初始化类加载器,并解析server.xml和启动这些组件。在内嵌式的模式下,Bootstrap和Catalina的工作就由SpringBoot来做了,SpringBoot调用了Tomcat的API来启动这些组件。那SpringBoot是如何完成调用的呢?查看SpringApplication类,在构造方法中有设置webApplicationType的代码,查看代码,可以看到是根据一些条件判断是否内部启动web容器的逻辑。构造方法查看后,查看SpringApplication类中的run()方法,run阶段有refreshContext方法。

Tomcat工作原理介绍_第8张图片 Tomcat工作原理介绍_第9张图片

refresh方法用来新建或者刷新一个ApplicationContext,在refresh方法中会调用onRefresh 方法,AbstractApplicationContext 的子类可以重写这个方法 onRefresh 方法,来实现特定 Context 的刷新逻辑,因此ServletWebServerApplicationContext 就是通过重写 onRefresh 方法来创建内嵌式的 Web 容器,具体创建过程如下图部分关键代码所示:最终实现内置启动tomcat的效果

Tomcat工作原理介绍_第10张图片

Tomcat工作原理介绍_第11张图片

Tomcat工作原理介绍_第12张图片

以上就是springboot集成tomcat的逻辑,在集成tomcat后,可以在application.properties中设置tomcat相关的参数,如下图所示,左图是在独立tomcat下的server.xml中配置相关参数,右图是在application.properties中设置相关参数。通过调节这些参数可以有效提升web应用的性能。

Tomcat工作原理介绍_第13张图片Tomcat工作原理介绍_第14张图片

除了设置线程数这些参数外,还可以在application.properties文件下设置tomcat日志相关的参数。

Tomcat工作原理介绍_第15张图片

Springboot默认内置的web服务器是Tomcat,如果要修改成其他Web服务器也可以,例如将Web服务器切换到Undertow。Undertow 是一个采用Java开发的灵活的高性能Web服务器,提供包括阻塞和基于NIO的非堵塞机制。Undertow是红帽公司的开源产品,是Wildfly默认的Web服务器。修改pom.xml文件即可完成切换。从依赖信息里移除Tomcat配置,添加新的web服务器依赖即可。

Tomcat工作原理介绍_第16张图片Tomcat工作原理介绍_第17张图片

以上就是对Tomcat相关工作原理的学习。

你可能感兴趣的:(Java系列,tomcat)