俗话说,站在巨人的肩膀上看世界,当你一般学习的时候,你先看看整体,然后一个接一个地突破。最后,形成一个思路并了解具体细节。 Tomcat的结构非常复杂,但Tomcat非常模块化。我找到了Tomcat的核心模块,问题可以解决,了解Tomcat的整体架构对于了解Tomcat的未来非常重要!
首先,Tomcat顶级架构
首先上传Tomcat的顶级结构图(图A),如下所示:
Tomcat中最顶层的容器是Server,它代表整个服务器。从上图中可以看出,服务器可以包含至少一个特定服务的服务。
服务主要由两部分组成:连接器和容器。从上图可以看出,Tomcat的核心是这两个组件,它们的作用如下:
Tomcat中只有一个服务器,一个服务器可以包含多个服务,一个服务只有一个容器,但可以有多个连接器。这是因为服务可以有多个连接,例如同时提供Http和Https链接。与同一协议的不同端口的连接如下(引擎,主机,上下文将在下面提到):
多个连接器和一个容器构成一个服务。通过服务,您可以在外部提供服务,但服务需要一个生活环境。有人必须给她生命并掌握生死的力量。所以!整个Tomcat生命周期由Server控制。
另外,可以在tomcat的conf目录中的server.xml配置文件中看到上述包含关系或父子关系。删除评论内容后,下图是完整的server.xml配置文件(Tomcat版本)。作为8.0)可以在Tomcat网站上查看配置文件的详细信息:http://tomcat.apache.org/tomcat-8.0-doc/index.html
通过以下结构图也可以更清楚地理解上述配置文件:
“服务器”选项卡设置的端口号为8005,shutdown=“SHUTDOWN”,表示在端口8005上监视“SHUTDOWN”命令。如果收到,则关闭Tomcat。服务器有一个服务,当然,它也可以配置。有多个服务。服务左侧的内容属于Container,服务是连接器。
二,Tomcat顶级架构总结:
(1)Tomcat中只有一台服务器,一台服务器可以有多个服务,一台服务可以有多个连接器和一个容器。
(2)服务器负责Tomcat的整个生死;
(4)服务是提供外部服务;
(5)连接器用于接受请求并将请求封装到请求和响应中以进行特定处理;
(6)Container用于封装和管理servlet,并专门处理请求请求;
了解整个Tomcat顶层的层次结构以及各个组件之间的关系和功能,对于大多数开发人员来说,服务器和服务对我们来说真的很遥远,我们在开发过程中配置的大部分内容都是如此。它属于Connector和Container,所以我们来谈谈Connector和Container。
第三,Connector和Container之间的微妙关系
从上面我们可以粗略地知道,在向Tomcat发送请求之后,它将首先通过服务然后将被移交给我们的连接器。 Connector用于接收请求,并将收到的请求封装到Request和Response中以进行特定处理。在封装Request和Response之后,然后由Container处理它。在Container完成处理请求后,它将返回到Connector。最后,连接器通过Socket将处理结果返回给客户端,以便处理整个请求!
Connector的底层使用Socket进行连接。 Request和Response是根据HTTP协议封装的,因此Connector需要同时实现TCP/IP协议和HTTP协议!由于Tomcat处理请求,它必须首先接收请求。要接收请求,我们首先需要查看连接器!
四,连接器架构分析
Connector用于接受请求并将请求封装到Request和Response中,然后将其交给Container进行处理。处理Container后,将其移交给Connector并返回给客户端。
因此,我们可以从四个方面理解Connector:
首先看一下连接器的结构图(图B),如下图所示:
Connector使用ProtocolHandler来处理请求。不同的ProtocolHandler表示不同的连接类型。例如,Http11Protocol使用普通的Socket连接,而Http11NioProtocol使用NioSocket进行连接。
ProtocolHandler由三个组件组成:端点,处理器,适配器。
(1)端点用于处理底层Socket的网络连接。处理器用于将端点接收的Socket封装到请求中,并且适配器用于将请求传递到容器以进行特定处理。
(2)由于Endpoint处理底层Socket网络连接,因此Endpoint用于实现TCP/IP协议,而Processor用于实现HTTP协议。适配器将请求调整到Servlet容器以进行特定处理。
(3)端点抽象实现AbstractEndpoint定义了Acceptor和AsyncTimeout两个内部类和一个Handler接口。 Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理收到的Socket,处理器在内部调用进行处理。
在这一点上,我们应该很容易回答(1)(2)(3)的问题,但是(4)仍然不知道,然后让我们看看容器的处理方式以及处理后如何处理容器。结果是否返回到连接器?
五,容器架构分析
Container用于封装和管理Servlet,并专门处理Request请求。它在Connector中包含四个子容器。结构如下(图C):四个子容器的作用是:
让我们看一下Tomcat文件目录进行比较,如下所示:
Context和Host之间的区别在于Context表示应用程序。在我们的Tomcat的默认配置中,webapps下的每个文件夹目录都是一个Context。 ROOT目录存储主应用程序,其他目录存储子应用程序。 Webapps是一个主机站点。
当我们访问应用程序上下文时,如果它在ROOT下,则可以使用域名直接访问它,例如:www.ledouit.com。如果是Host(webapps)下的其他应用程序,可以使用www.ledouit.com/docs完成。当然,可以设置访问默认的指定根应用程序(ROOT),但主机站点下的默认主要用途是在ROOT目录下。
看到这里我们知道Container是什么,但仍然不知道如何处理Container以及如何在处理后将处理结果返回到Connector?别担心!我们来谈谈如何处理Container!
Container如何处理请求?
使用Pipeline-Valve管道处理容器处理请求! (阀门是阀门的意思)
Pipeline-Valve是责任链模式。责任链模式意味着在请求处理过程中,许多处理器依次处理请求。每个处理器负责进行自己的处理。处理完成后,返回处理后的请求。 ,让下一个过程继续进行。
但是,Pipeline-Valve使用的责任链模型与正常的责任链模型有些不同!有两个主要区别:
我们知道Container包含四个子容器,对应于四个子容器的BaseValve是:StandardEngineValve,StandardHostValve,StandardContextValve,StandardWrapperValve。
Pipeline的处理流程图如下(图D):
(1)接收到请求后,Connector将首先调用最顶层容器的Pipeline进行处理。这里最顶层容器的Pipeline是EnginePipeline(Engine的管道);
(2)EngineValve1,EngineValve2等将在Engine管道中执行,然后执行StandardEngineValve。在StandardEngineValve中,将调用Host管道,然后依次执行Host的HostValve1,HostValve2等,然后执行StandardHostValve,然后执行调用。 Context管道和Wrapper管道最终被执行到StandardWrapperValve中。(3)当执行到StandardWrapperValve时,它将在StandardWrapperValve中创建FilterChain并调用其doFilter方法来处理请求。此FilterChain包含我们配置为匹配请求的Filter和Servlet,其doFilter方法将依次调用所有这些。过滤器的doFilter方法和servlet的服务方法,因此处理请求!
(4)在执行了所有Pipeline-Valve之后,处理了特定请求,返回的结果可以移交给Connector,Connector通过Socket将结果返回给客户端。