文章目录
- 一、Tomcat的核心模块(核心组件)
- 二、Engine 组件
- 1.核心类与依赖图
- 2.核心类源码分析
- 构造函数:
- 初始化方法 init:
- 启动方法 start:
- 3.Engine的启动过程
- 总结
一、Tomcat的核心模块(核心组件)
Tomcat主要是由这几个模块组成的:
-
Server:
Server 是最外层的组件,他在Java虚拟集中是单例,主要是用来管理容器下各个Serivce组件的生命周期。 -
Service:
Server 它将一个或多个连接器(Connector)组件绑定到一个单独的引擎(Engine)上。Service仅仅是一个分组结构,他只是充当架构的一个层面,它并不包含任何其他的功能。 -
Connector:
连接器,处理与客户端的通信,它负责接收客户请求,以及向客户返回响应结果,每个连接器监控一个指定的IP及端口并通过指定的协议做出响应。可以配置多个连接器使用。 -
Engine:
引擎,表示一个特定的 Service 的请求处理流水线,从连接器接收和处理所有的请求,将响应返回给适合的连接器,通过连接器传输给用户。在一个服务中(Service)只能有一个引擎。 -
Host:
虚拟主机,Host 是 Engine 的子容器,一个 Engine 可以包含多个 Host。这个虚拟主机的作用就是运行应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分它们。 -
Context:
他代表一个部署的 Web 应用程序本身,它具备了 Servlet 运行的基本环境。一个 Host 可以包含多个Context,每个 Context
都有一个唯一的路径。Context表示了一个应用的生命周期。
所有客户端的请求都会在连接器(Connector)接受,然后在引擎中(Engine),通过管道(PipeLine),在管道中可以加入各种自定义的阀门(Valve),做拦截,做过滤。所以 Engine 组件,在整次请求中,起着承前启后的关键作用。
下面,我们就着重分析 Engine 组件。
二、Engine 组件
1.核心类与依赖图
Engine 组件的核心类是 StandardEngine
该类的依赖图如下:
从图中可以看到,他也是通过 Lifecycle,来实现他的生命周期管理;并且 Engine 他还是一个容器,实现了Container
2.核心类源码分析
构造函数:
public StandardEngine() {super();pipeline.setBasic(new StandardEngineValve());/* Set the jmvRoute using the system property jvmRoute */try {setJvmRoute(System.getProperty("jvmRoute"));} catch(Exception ex) {log.warn(sm.getString("standardEngine.jvmRouteFail"));}// By default, the engine will hold the reloading threadbackgroundProcessorDelay = 10;}
可以看出来,主要是给StandardEngine的管道(pipeline)添加了阀门 Value
在 Tomcat 的源码中,以 Value 结尾的类,都是阀门,阀门就是用来提供一些功能的代码,封装成类
打开阀门的核心代码可以看到,他只是拿到 Host,并且调用他通道里面的 Value
final class StandardEngineValve extends ValveBase {//------------------------------------------------------ Constructorpublic StandardEngineValve() {super(true);}@Overridepublic final void invoke(Request request, Response response)throws IOException, ServletException {// Select the Host to be used for this RequestHost host = request.getHost();if (host == null) {// HTTP 0.9 or HTTP 1.0 request without a host when no default host// is defined.// Don't overwrite an existing errorif (!response.isError()) {response.sendError(404);}return;}if (request.isAsyncSupported()) {request.setAsyncSupported(host.getPipeline().isAsyncSupported());}// Ask this Host to process this requesthost.getPipeline().getFirst().invoke(request, response);}
}
初始化方法 init:
既然 Engine 实现了 Lifecycle,那他自然也继承了里面的生命周期方法,在启动时,会触发 initInternal() 方法
源码中看到,在这里初始化以及获取了 Realm
Realm,可以翻译为 " 域 ",在 Tomcat 中,他是一个存储用户名,密码以及和用户名相关联的角色的 " 数据库 "
@Overrideprotected void initInternal() throws LifecycleException {// Ensure that a Realm is present before any attempt is made to start// one. This will create the default NullRealm if necessary.getRealm();super.initInternal();}
启动方法 start:
上面说到 Engine 实现了 Lifecycle,继承了他的生命周期方法,还有比较核心的 startInternal()
@Overrideprotected synchronized void startInternal() throws LifecycleException {// Log our server identification informationif (log.isInfoEnabled()) {log.info(sm.getString("standardEngine.start", ServerInfo.getServerInfo()));}// Standard container startupsuper.startInternal();}
他调用了其父类的 startInternal()
@Overrideprotected synchronized void startInternal() throws LifecycleException {// Start our subordinate components, if anylogger = null;getLogger();Cluster cluster = getClusterInternal();if (cluster instanceof Lifecycle) {((Lifecycle) cluster).start();}Realm realm = getRealmInternal();if (realm instanceof Lifecycle) {((Lifecycle) realm).start();}// Start our child containers, if anyContainer children[] = findChildren();List<Future<Void>> results = new ArrayList<>();for (Container child : children) {results.add(startStopExecutor.submit(new StartChild(child)));}MultiThrowable multiThrowable = null;for (Future<Void> result : results) {try {result.get();} catch (Throwable e) {log.error(sm.getString("containerBase.threadedStartFailed"), e);if (multiThrowable == null) {multiThrowable = new MultiThrowable();}multiThrowable.add(e);}}if (multiThrowable != null) {throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),multiThrowable.getThrowable());}// Start the Valves in our pipeline (including the basic), if anyif (pipeline instanceof Lifecycle) {((Lifecycle) pipeline).start();}setState(LifecycleState.STARTING);// Start our threadif (backgroundProcessorDelay > 0) {monitorFuture = Container.getService(ContainerBase.this).getServer().getUtilityExecutor().scheduleWithFixedDelay(new ContainerBackgroundProcessorMonitor(), 0, 60, TimeUnit.SECONDS);}}
这一大段代码中,有几个比较核心的地方:
- 遍历找到其所有子容器,并启动他们
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {results.add(startStopExecutor.submit(new StartChild(child)));
}
- 启动他(Engine )的管道,并执行管道里面的阀门
if (pipeline instanceof Lifecycle) {((Lifecycle) pipeline).start();
}
- 调用监听事件
在父类的 startInternal() 方法中,用下面这行,调用了 LifecycleBase 里面的方法
setState(LifecycleState.STARTING);
最终定位到,这个方法,调用其注册的监听事件
protected void fireLifecycleEvent(String type, Object data) {LifecycleEvent event = new LifecycleEvent(this, type, data);for (LifecycleListener listener : lifecycleListeners) {listener.lifecycleEvent(event);}}
传进来的,是 EngineConfig ,他实现了 LifecycleListener ,其监听器处理逻辑也很简单,只是记录一下操作日志
3.Engine的启动过程
总结
欢迎指出我的错误!