Tomcat的系统架构与设计模式

Tomcat总体设计

Tomcat的心脏有两个关键组件:Connector和Container。Connector是可以被替换的,一个Container可以选择对应多个Connector。多个Connector和一个Container形成了一个Service,有了一个Service就可以对外提供服务了。Service还有个生存环境,控制其生命周期,这个就是Server

Service

Tomcat中的Connector、Container可以作为一个整体,Container主要处理Connector接受的请求,而Service将两者组装在一起。一个Service可以设置多个Connector,但是只能有一个Container容器

Service接口主要是关联上述两者,但是没有在该接口中规定一定要控制其下方的组件的生命周期,所有组件的生命周期在Lifecycle接口中控制

Service的标准实现类是StandardService,它同时还实现了Lifecycle接口

StandardService中主要几个方法的实现逻辑:

  1. setContainer:首先判断当前Service有没有关联Container,如果有则去掉这个关联关系,如果这个Container已经启动则结束它的生命周期,然后替换成新的,初始化新的生命周期。修改Container时,要将新的关联到每个Connector(两者之间单向关联)
  2. addConnector:设置关联关系,初始化工作,开始新的生命周期。存储Connector使用的是数组而不是List,这里的数组没有在刚开始分配一个固定大小,而是重新创建一个当前大小的数组对象,然后将原来的数组对象复制到当前数组对象中

Server

Server的作用就是,提供一个接口让其他程序可以访问到这个Service集合,同时维护所包含的所有Service的生命周期

Server的标准实现类是StandardServer,其也实现了Lifecycle接口,下面是其中一个重要的方法:

  1. addServer:Server管理Service就像Service管理Connector一样,也是采用数组的模式

Lifecycle

Tomcat中组件的生命周期都是通过Lifecycle接口来控制的,组件只要继承这个接口并实现其中的方法就可以统一被拥有它的组件控制,这样向上拓展,最高级的Server就可以控制所有的组件了

除了控制生命周期的Start和Stop方法外,还有一个监听机制,可以在生命周期开始和结束的时候做一些额外的操作

生命周期的控制都是从上而下,从最高级组件开始逐级控制到子组件

Connector组件

Connector组件时Tomcat的两个核心组件,其主要任务时负责接收浏览器发来的TCP连接请求,创建一个Request和Response对象分别用于和请求端交换数据

之后会产生一个线程来处理这个请求,并把产生的Request和Response对象传给处理这个请求的线程,之后处理这个线程就是Container组件的事情了

HttpConnector的Start方法作为启动方法,当方法执行到其中的threadSatrt方法时,就会进入等待请求的状态,直到一个新的请求到来才会激活它继续执行,这个激活是在HttpProcessor的assign方法中

在激活方法中,会将请求的Socket赋给当前处理的Socket(创建HttpProcessor时),而后激活run方法,处理这次请求,其中包括解析Socket的过程

当Connector将Socket连接封装成Request和Response对象后,后面就是Container来处理了

Container组件

Container容器的设计时典型的责任链设计模式,由四个子容器组件组成:Engine、Host、Context、Wrapper,这四个也是父子的包含关系

通常一个Servlet class对应一个Wrapper,如果有多个Servlet就需要多个Wrapper,如果有多个Wrapper就需要一个如Context来管理

Context可以定义在Host中,Host不是必需的,但是如果要运行war程序,就需要Host来解析web.xml文件

如果有多个Host就需要一个Engine容器

Engine容器

其只定义了一些基本的关联关系,标准实现类是StandardEngine

由于该容器没有父容器,所以如果调用setParent方法是会报错的,而添加的子容器也只能是Host类型

它的初始化方法也就是初始化和它相关联的组件,以及一些事件的监听

Host容器

Engine的子容器,一个Host代表一个虚拟主机,作用是运行多个应用,负责安装和展开这些应用,并且为应用做标识来区分它们

其子容器一般都是Context,除了关联子容器外,还保存了一个主机应有的信息

Context容器

Context代表Servlet的Context,具备Servlet运行的基本环境,理论上,一个简单的Tomcat可以没有Engine和Host,只有Context就可以运行Servlet、

Servlet在Context中是以Wrapper出现的,Tomcat5以前是通过一个Mapper类来管理找到正确的Servlet并执行,而Tomcat5之后被移到了Request中

Context从Start方法开始准备Servlet的运行环境,其主要作用是设置各种资源属性和管理组件,然后可以启动子容器和Pipeline

当Context的配置文件中的reloadable属性被置为true后,如果war被修改,Tomcat自动加载这个应用,这个过程实在StandardContext的backgroundProcess方法中实现的。这里调用的reload方法是先调用stop方法,再调用start方法完成一次重新加载

而这个backgroundProcess方法是在ContainerBase类中定义的内部类ContainerBackgroundProcesso中被周期调用的,这个类运行在一个后台线程中,会周期性的进行调用

Wrapper容器

其代表一个Servlet,负责管理Servlet的装载、初始化、执行以及资源回收

没有子容器,所以调用addChild会报错

Wrapper容器的实现类是StandardWrapper,该实现类还实现了ServletConfig用来初始化Servlet

其中有个loadServlet方法,基本描述了对Servlet的操作。一旦装载Servlet后就会调用init方法,同时传递StrandradWrapperFacade对象给Servlet,这个对象包装了StandradWrapper,同时封装了Servlet可以获得的信息