工作分析原理与方法

工作分析原理与方法,第1张

分析Tomcat的工作原理

本文主要介绍Tomcat的工作原理,帮助您了解Tomcat的工作原理以及处理请求的过程和分析。感兴趣的朋友可以了解一下。

跳羚就像一条巨蟒,慢慢缠绕我们,麻痹我们。不得不承认,SpringBoot的使用确实提高了工作效率,但同时也让我们忘记了很多技巧。刚入社的时候还是通过Tomcat手动部署JavaWeb项目,经常调Tomcat的性能。另外,你需要自己整理好JAR之间的关系,避免JAR丢失和版本冲突导致的服务启动异常的问题。到现在,所有这些繁琐重复的工作都交给了SpringBoot,我们可以更专注于业务逻辑。但是,了解Tomcat的工作原理和处理请求的方式和分析Spring框架的源代码一样重要。至少面试官喜欢问这些底层原理和设计思路。希望这篇文章能给你一些帮助。

Tomcat的整体架构

Tomcat是一个免费的、开源的轻量级Web应用服务器。适用于低并发的中小型企业项目。

文件目录结构

下面是Tomcat8的主目录结构

目录 函数声明 Bin 存储可执行文件,比如启动和关机 Conf 存储配置文件,例如核心配置文件server.xml和应用程序默认部署描述文件web.xml Lib 存储Tomcat 需要的jar包Logs 存储正在运行的日志文件 webapps 存储默认的web应用程序部署目录 Work 一个临时目录,用于存储web应用程序代码的生成和编译文件

功能组件结构

Tomcat有两个核心功能,连接器Connector,负责接收和反馈外部请求,容器Container,负责处理请求。其中,连接器和容器相辅相成,共同构成了基本的web服务。每个Tomcat服务器可以管理多个服务。

包裹 功能 连接器 负责接收反馈请求。它是Tomcat与外界的交通枢纽。监控端口接收外界的请求,处理后传递给容器进行业务处理,最后将容器的处理结果反馈给外界。 容器 负责内部处理业务逻辑。它由四个容器组成:引擎、主机、上下文和包装器,用于管理和调用Servlet相关的逻辑。 Service 对外提供的Web服务。它主要包括两个核心组件:连接器和容器,以及其他功能组件。Tomcat可以管理多个相互独立服务。

Tomcat连接器核心原理

Tomcat连接器框架-coyote

连接器的核心功能

1.监控网络端口以接收和响应网络请求。

第二,网络字节流处理。接收到的网络字节流转换成Tomcat请求,然后转换成标准的ServletRequest给容器,来自容器的ServletResponse转换成Tomcat响应,然后转换成网络字节流。

连接器模块的设计

为了满足连接器的两个核心功能,我们需要一个通信端点来监控端口;需要处理器来处理网络字节流;最后,需要一个适配器将处理后的结果转换成容器所需的结构。

包裹 功能 Endpoint endpoint,用于处理套接字接收和发送的逻辑。接收方在内部监视请求,处理程序处理数据,AsyncTimeout检查请求是否超时。具体实现有NioEndPoint、AprEndpoint等。 Processor 处理器,负责构建Tomcat请求和响应对象。具体实现有Http11Processor、StreamProcessor等。 Adapter adapter,实现Tomcat请求和响应、ServletRequest和ServletResponse之间的相互转换。这是经典的适配器设计模式。 ProtocolHandler 协议处理器,将不同的协议和通信方式组合封装到相应的协议处理器中。比如Http11NioProtocol封装了HTTP+NIO。

org.apache.coyote对应的源码包路径对应的结构图如下

Tomcat容器核心原则

Tomcat容器框架-catalina

容器结构分析

每个服务将包含一个容器。一个容器可以通过一个引擎管理多个虚拟主机。每个虚拟主机可以管理多个Web应用程序。每个Web应用程序都有多个Servlet包装器。引擎、主机、上下文和包装器,属于父子关系。

容器 功能 Engine Engine,管理多个虚拟主机。 Host 虚拟主机,负责Web应用的部署。 Context Web应用程序,它包含多个Servlet包装器。 包装器 包装器,容器的最底层。封装Servlet,负责实例的创建、执行和销毁。

org.apache.coyote对应的源码包路径对应的结构图如下

容器请求处理

容器的请求处理过程是一层一层的调用四个容器,引擎、主机、上下文、包装器,最后在Servlet中执行相应的业务逻辑。每个容器都会有一个通道管道,每个通道都会有一个基本的阀门(比如StandardEngineValve),类似于处理请求和响应的闸门。流程图如下。

Tomcat请求处理流程

以上知识点已经零零碎碎的介绍了Tomcat如何处理请求。简单理解就是连接器的处理流程+容器的处理流程=Tomcat处理流程。哈!那么问题来了,Tomcat是怎么通过请求路径找到对应的虚拟站点的呢?如何找到对应的Servlet?

映射器函数介绍

需要引入上面没有介绍的组件映射器。顾名思义,它的功能是提供请求路径的路由映射。根据哪个容器来处理请求URL地址匹配。每个容器都有自己的映射器,比如MappedHost。不知道大家有没有回忆过被Mapper类支配不被发现的恐惧。以前每次编写一个完整的函数,都需要在web.xml中配置映射规则,当文件越来越大的时候,各种问题也出现了。

HTTP请求过程

打开tomcat/conf目录中的server.xml文件来分析http://localhost:8080/docs/api请求。

步骤1:连接器侦听的端口是8080。连接器接受了请求,因为请求的端口与被监视的端口相同。

第二步:因为引擎默认的虚拟主机是localhost,虚拟主机的目录是webapps。于是请求找到了tomcat/webapps目录。

第三步:解析出的docs是web程序的应用名,也就是context。此时,请求继续从webapps目录中查找docs目录。有时我们也会省略应用程序名。

步骤4:解析的api是特定的业务逻辑地址。此时,你需要从docs/WEB-INF/web.xml中找到映射关系,最后调用具体的函数。

<?xmlversion="1.0"encoding="UTF-8"?> <Serverport="8005"shutdown="SHUTDOWN"> <Servicename="Catalina"> <!--连接器监听端口是8080,默认通讯协议是HTTP/1.1--> <Connectorport="8080"protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/> <!--名字为Catalina的引擎,其默认的虚拟主机是localhost--> <Enginename="Catalina"defaultHost="localhost"> <!--名字为localhost的虚拟主机,其目录是webapps--> <Hostname="localhost"appBase="webapps" unpackWARs="true"autoDeploy="true"> </Host> </Engine> </Service> </Server>

SpringBoot如何开始嵌入式Tomcat

SpringBoot一键启动服务功能,让很多刚步入社会的朋友忘记了什么是Tomcat。随着硬件性能的不断提升,普通中小型项目可以直接用内置的Tomcat启动。但是,一些较大的项目可能会使用Tomcat集群和调优,内置的Tomcat可能无法满足需求。

我们先从源代码来分析SpringBoot是如何启动Tomcat的。以下是SpringBoot2.x的代码

代码从main方法开始,并执行run方法来启动项目。

SpringApplication.run

从运行方法的角度来看,找到一种刷新应用程序上下文的方法。

this.prepareContext(context,environment,listeners,applicationArguments,printedBanner); this.refreshContext(context); this.afterRefresh(context,applicationArguments);

单击refreshContext方法以查找刷新方法。并逐层寻找其父类。

this.refresh(context);

在AbstractApplicationContext类的refresh方法中,有一行逻辑调用子容器refresh。

this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh();

点击onRefresh方法,找到ServletWebServerApplicationContext的实现方法。这里终于看到了希望。

protectedvoidonRefresh(){ super.onRefresh(); try{ this.createWebServer(); }catch(Throwablevar2){ thrownewApplicationContextException("Unabletostartwebserver",var2); } }

单击createWebServer方法,找到从工厂类获取WebServer的代码。

if(webServer==null&&servletContext==null){ ServletWebServerFactoryfactory=this.getWebServerFactory(); //获取webserver this.webServer=factory.getWebServer(newServletContextInitializer[]{this.getSelfInitializer()}); }elseif(servletContext!=null){ try{ //启动webserver this.getSelfInitializer().onStartup(servletContext); }catch(ServletExceptionvar4){ thrownewApplicationContextException("Cannotinitializeservletcontext",var4); } }

点击getWebServer方法,找到TomcatServletWebServerFactory的实现方法,对应Jetty和Undertow。下面是连接器、引擎、虚拟站点等的基本配置。

publicWebServergetWebServer(ServletContextInitializer...initializers){ Tomcattomcat=newTomcat(); FilebaseDir=this.baseDirectory!=null?this.baseDirectory:this.createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connectorconnector=newConnector(this.protocol); tomcat.getService().addConnector(connector); this.customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); this.configureEngine(tomcat.getEngine()); Iteratorvar5=this.additionalTomcatConnectors.iterator(); while(var5.hasNext()){ ConnectoradditionalConnector=(Connector)var5.next(); tomcat.getService().addConnector(additionalConnector); } this.prepareContext(tomcat.getHost(),initializers); returnthis.getTomcatWebServer(tomcat); }

服务启动后将打印日志。

o.s.b.w.embedded.Tomcat.Tomcatwebserver:用端口初始化的Tomcat:8900(http)
o.Apache.catalina.core.standardservice:启动服务[Tomcat]
org.Apache.catalina.core.standardEngine:启动Servlet引擎:ApacheTomcat/8.5.34
o.a.catalina.core.aprlivecyclelistene...
o.a.c.c.C.[Tomcat]。[本地主机]。[/]:正在初始化SpringembeddedWebApplicationContext
o.s.web.context.contextloader:RootWebApplicationContext:初始化在16858毫秒内完成

END

文章到此结束。我再也憋不住了。周末一整天都没写源码,只好放到下一章了。照片又要报废了。请指出任何错误。

这就是Tomcat工作的细节。关于Tomcat如何工作的更多信息,请关注我们的其他相关文章!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/774309.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-03
下一篇 2022-05-03

发表评论

登录后才能评论

评论列表(0条)

保存