当前位置: 首页 > 科技观察

说说让面试官瑟瑟发抖的Tomcat系统架构

时间:2023-03-20 16:13:09 科技观察

前言具体细节,Tomcat的结构非常复杂,但是Tomcat非常模块化。只有找到Tomcat的核心模块,问题就迎刃而解了。了解Tomcat的整体结构对于以后深入理解Tomcat非常重要!一、Tomcat顶层架构首先来一张Tomcat的顶层结构图(图A),如下:Tomcat中的顶层容器是Server,它代表了整个服务器。从上图可以看出,一个Server至少可以包含一个Service。为具体提供服务。Service主要由两部分组成:Connector和Container。从上图可以看出,Tomcat的心脏就是这两个组件。它们的作用如下:一个Tomcat只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但可以有多个Connector。这是因为一个服务可以有多个连接,比如同时提供Http和Https链接,或者提供同一个协议的不同端口的连接。示意图如下(下面会提到Engine、Host、Context):多个Connector和一个Container组成一个Service,有了Service,就可以对外提供服务,但是Service也需要一个生存环境,必须有能够赋予她生命,掌控她生死的人,那一定是Server!所以整个Tomcat的生命周期都是由Server控制的。另外,上述的包含关系或者父子关系可以在tomcat的conf目录下的server.xml配置文件中看到。下图是删除注释内容后完整的server.xml配置文件(Tomcat版本为8.0)详细配置文件内容可以在Tomcat官网查看:http://tomcat.apache.org/tomcat-8.0-doc/index.html上面的配置文件通过下面一张结构图也可以更清楚理解:Server标签上设置的端口号为8005,shutdown="SHUTDOWN",表示在8005端口监听"SHUTDOWN"命令,如果收到,Tomcat将关闭。一个Server有一个Service,当然可以配置。有多个服务。Service左边的内容属于Container,Service下面是Connector。2、Tomcat顶层架构总结:(1)Tomcat中只有一个Server,一个Server可以有多个Service,一个Service可以有多个Connector和一个Container;(2)Server负责整个Tomcat的生死;(4)服务为对外提供服务;(5)Connector用于接受请求,将请求封装成Request和Response进行具体处理;(6)Container用于封装和管理Servlet,具体处理request请求;了解了Tomcat的顶层分层架构和各个组件的关系和作用,对于大部分开发者来说,Server和Service对我们来说真的很遥远,而我们开发中大部分的配置内容都属于Connector和Container,下面介绍一下接下来是连接器和容器。3、Connector和Container的微妙关系从上面的内容我们可以大致知道,一个请求发送到Tomcat之后,首先会经过Service,然后交给我们的Connector。Connector用于接收请求,并将接收到的请求封装成Request和Response。处理,Request和Response封装后,交给Container处理。Container处理完请求后,返回给Connector。最后Connector将处理结果通过Socket返回给客户端,这样整个请求就处理完了!Connector***层使用Socket连接,Request和Response按照HTTP协议进行封装,所以Connector需要同时实现TCP/IP协议和HTTP协议!Tomcat既然处理请求,就必须先接收到这个Request,要接收到请求,首先要看Connector!4、Connector架构分析Connector用于接受请求,将请求封装成Request和Response,然后交给Container处理。Container处理完成后,交给Connector返回给client。因此,我们可以将Connector分为四个方面进行理解:首先,看一下Connector的结构图(图B),如下图:Connector使用ProtocolHandler来处理请求,不同的ProtocolHandlers代表不同的连接类型,如:Http11Protocol使用普通Socket连接,Http11NioProtocol使用NioSocket连接。其中,ProtocolHandler由三个组件组成:Endpoint、Processor、Adapter。(1)Endpoint用于处理底层Socket的网络连接,Processor用于将Endpoint收到的Socket封装成Request,Adapter用于将Request交给Container进行具体处理。(2)Endpoint处理底层的Socket网络连接,所以使用Endpoint来实现TCP/IP协议,使用Processor来实现HTTP协议。Adapter将请求适配到Servlet容器中进行具体处理。(3)Endpoint的抽象实现定义了两个内部类Acceptor和AsyncTimeout,在AbstractEndpoint中定义了一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时时间,Handler用于处理接收到的Socket,内部调用Processor进行处理。至此,我们应该很容易回答问题(1)(2)(3),但是(4)还是未知数,那么我们来看看Container是如何处理的,完成后又是如何处理的。5、Container架构分析Container用于封装和管理Servlet,具体处理Request请求。连接器内部有4个子容器。结构图如下(图C):4个子容器的作用分别是:我们找一个Tomcat文件目录进行对比,如下图:Context和Host的区别在于Context代表一个应用,而我们Tomcat中默认配置下的webapps下的每一个文件夹目录都是一个Context,其中ROOT目录下存放的是主应用,其他目录下存放的是子应用,整个webapps就是一个Host站点。当我们访问应用Context时,如果是ROOT下,我们可以直接使用域名访问,例如:www.ledouit.com,如果是Host(webapps)下的其他应用,我们可以使用www.ledouit.com/docs访问,当然可以设置默认指定根应用(ROOT),但是Host站点下的默认主应用在ROOT目录下。看到这里,我们知道什么是Container了,但是我们还是不知道Container是怎么处理的,处理完后如何将处理后的结果返回给Connector?不用担心!下面开始讨论Container是如何处理的!6.Container如何处理请求?Container处理请求是使用Pipeline-Valve管道处理的!(Valve的意思是阀门)Pipeline-Valve是责任链模式,意思是在处理一个请求的过程中有很多个处理器轮流处理请求,每个处理器负责自己对应的处理,并返回处理完后的请求,再让下一个处理器继续处理。但!Pipeline-Valve使用的责任链模型与普通的责任链模型有些不同!区别主要有以下两点:我们知道Container包含四个子容器,这四个子容器对应的BaseValve分别是:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。Pipeline的处理流程图如下(图D):(1)Connector收到请求后会先调用最顶层容器的Pipeline进行处理,其中最顶层容器的Pipeline为EnginePipeline(Engine的管道);(2)在Engine管道中会依次执行EngineValve1、EngineValve2等,***会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后依次执行Host的HostValve1、HostValve2等,***执行StandardHostValve,然后依次调用Context的pipeline和Wrapper的pipeline,最终执行到StandardWrapperValve。(3)StandardWrapperValve执行时,会在StandardWrapperValve中创建一个FilterChain,调用其doFilter方法处理请求。这个FilterChain包含了我们配置的匹配请求的Filter和Servlet,它的doFilter方法会依次调用它们。Filter的doFilter方法和Servlet的service方法,让请求得到处理!(4)所有Pipeline-Valves执行完毕,具体请求处理完成后,即可将返回结果交给Connector。,Connector通过Socket将结果返回给客户端。综上所述,我们对Tomcat的整体架构有了一个大概的了解。从图A、B、C、D,我们可以看到每个组件的基本元素和功能。我们心里应该有个大纲吧!如果面试的时候让你简单说说Tomcat,你能脱口而出上面的内容吗?当你能脱口而出的时候,面试官一定会对你刮目相看的!