- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
系列文章目录和关于我 。
参考书籍《Tomcat架构解析》
本文沿袭《Tomcat架构解析》中启发式的方式来总结Tomcat总体架构 。
假设当前我们要编写一个web应用服务器,web应用服务器最基本的功能是接受客户端发送的请求数据并进行解析,完成相关的业务处理,然后将处理结果作为响应返回给请求计算机,于是我们定义了下面Server类 。
从上面这段话来看,如果我们将上述功能全部让Server去做实现,那么让请求监听和请求处理耦合度很高,不利于扩展,比如监听方式发生变化(比如之前使用BIO,现在使用NIO),或者请求处理方式改变(之前遵循Servlet规范,请求交给Servlet对象处理,现在适配另外一种规范)这种变化会导致我们在Server对象中修改代码,不满足开闭原则,Server对象承受了太多,也不符合单一职责.
如何解决请求监听和请求处理耦合度很高的问题?加一层就好.
Connector 。
Connector负责开启socket并且监听客户端请求,返回响应数据.
Engine 。
Engine负责处理具体的请求 。
如是我们有下面这种设计 。
这种设计需要server维护Connector和Engine的关系,才可以将Connector的请求交给对应Engine 。
并且无法做到一个Tomcat服务器运行多个服务,比如订单服务,用户服务。将Connector和Engine都交给Server处理,无法实现服务间的隔离.
如何实现服务间的隔离?加一层就好 。
Server 表示Tomcat服务器,一个Tomcat服务器可以部署多个服务,比如订单服务,用户服务。这里的服务就是Service.
由Service负责当前自己服务中的维护Connector 和 Engine,Server负责管理多个服务 。
Context 。
应用服务器是用来部署并允许web应用的,是一个运行环境,而不是一个独立业务处理系统,因此在Engine容器需要支持管理web应用,这里便是使用Context来表示一个web应用 。
Host 。
Tomcat除了可以支持多个web应用之外,还需要可以支持多域名服务,比如一个主机可以承担多个域名,比如newx.cuzz.com,game.cuzz,com。因此需要把每一个域名视为一个虚拟主机,在每一个虚拟主机下包含多个web应用.
Wrapper 。
在一个web应用中可以包含多个不同的servlet实例处理来自不同连接的请求,因此还需要一个组件的概念来表示tomcat中的servlet,这个组件就是Wrapper 。
Container表示一类组件,它们负责接受来自客户端的请求,并返回响应数据,这个过程往往会委托其他组件去完成,但是本质上它们是一致的——都是接受请求,返回响应数据.
Container表示容器,可以添加并维护子容器,因此Engine,Host,Context,Wrapper均继承自Container 。
Container还提供了backgroundProcess方法,方便子类实现后台任务 。
可以看到上图中组件都存在start,stop等生命周期方法,因此Tomcat抽象出Lifecycle接口,表示生命周期,定义了init,start,stop,destory等生命周期回调方法。并且还提供了LifecycleListener使用监听器模式来实现生命周期事件监听.
为了增强扩展性,tomcat定义了Pipeline(管道)和Valve(阀),Pipeline使用职责链的方式串联多个Valve——来自客户端的请求如同流水一样流淌在管道中,收到每一个阀的作用.
Pipeline中维护了基础的Valve,始终位于Pipeline末端,通过Pipeline#addValve添加的Valve违约基础的Valve之前.
在Tomcat中Engine,Host,Context,Wrapper都有对应的Valve实现,同时维护了一个Pipeline,从而让我们可以对请求的处理进行扩展.
一个Connector处理请求的流程大致如下 。
这些操作会被委托给Endpoint,ProtocolHandler,Processor 。
在次之外Tomcat 还有一个Adapter接口,上面说到Processor会依赖Mapper实现请求映射,但是其实Proccessor并没有直接持有一个Mapper,而是持有一个Adapter,由Adapter负责实现请求映射并交由Container处理请求。Adapter在Tomcat中只有一个实现CoyoteAdapter.
CoyoteAdapter在Processor和 Mapper以及Container中横插一脚,实现Connector和Mapper以及Container的解耦.
结合tomcat整体架构后的图 。
Tomcat定义了Executor接口,只有一个实现类StandardThreadExecutor,目的是为了实现tomcat组件间的线程池共享,并且这个线程池由Service进行管理,即同一个Server中的组件可以共享一个线程池.
Tomcat通过类Catalina提供了一个Shell程序,用于解析server.xml创建各个组件。同时,负责启动、停止应用服务器(启动tomcat顶层组件Server) 。
Tomcat提供了Bootstrap作为应用服务器启动入口,Bootstrap负责反射创建Catalina实例,根据执行参数调用Catalina相关方法完成针对应用服务器的操作(启动、停止).
在Tomcat发布包中,Bootstrap位于$CATALINA_HOME/bin下,和Tomcat应用服务器完全松耦合(通过反射调用Catalina实例),它可以直接依赖JRE运行并为Tomcat应用服务器创建共享类加载器,用于构造Catalina实例及整个Tomcat服务器.
可以看到Tocmat的启动流程非常标准化,这得益于这些组件都实现了Lifecyle接口。首先是调用init初始化组件,然后调用start方法启动组件,每次调用都伴随着生命周期事件的触发.
应用程序的请求处理,开始于监听服务器socket端口接受到数据,结束与服务器处理结果写入Socket输出流.
在此过程中,服务器需要将请求内容按照协议内容进行解析,封装为对象,然后根据请求映射规则定位到具体Servlet,这个Servlet中就是我们业务逻辑(SpringMVC中是DispatcherServlet将进一步将请求分发到Controller)Servlet处理结束后,响应对象将按照协议内容写如输出流.
最后此篇关于Tomcat总体架构,启动流程与处理请求流程的文章就讲到这里了,如果你想了解更多关于Tomcat总体架构,启动流程与处理请求流程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在数据仓库上工作,对这个问题的一个合适的类比是我们有医疗保健从业者。医疗保健从业者具有多种专业属性,并且在多个团队和多个临床领域工作。 例如,您可能有一名护士作为救援人员/承包商/银行工作人员在多个团
我是一名优秀的程序员,十分优秀!