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 组件的核心类是 StandardEngine
该类的依赖图如下:
从图中可以看到,他也是通过 Lifecycle,来实现他的生命周期管理;并且 Engine 他还是一个容器,实现了Container
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 thread
backgroundProcessorDelay = 10;
}
可以看出来,主要是给StandardEngine的管道(pipeline)添加了阀门 Value
在 Tomcat 的源码中,以 Value 结尾的类,都是阀门,阀门就是用来提供一些功能的代码,封装成类
打开阀门的核心代码可以看到,他只是拿到 Host,并且调用他通道里面的 Value
final class StandardEngineValve extends ValveBase {
//------------------------------------------------------ Constructor
public StandardEngineValve() {
super(true);
}
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host 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 error
if (!response.isError()) {
response.sendError(404);
}
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
}
既然 Engine 实现了 Lifecycle,那他自然也继承了里面的生命周期方法,在启动时,会触发 initInternal() 方法
源码中看到,在这里初始化以及获取了 Realm
Realm,可以翻译为 " 域 ",在 Tomcat 中,他是一个存储用户名,密码以及和用户名相关联的角色的 " 数据库 "
@Override
protected 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();
}
上面说到 Engine 实现了 Lifecycle,继承了他的生命周期方法,还有比较核心的 startInternal()
@Override
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if (log.isInfoEnabled()) {
log.info(sm.getString("standardEngine.start", ServerInfo.getServerInfo()));
}
// Standard container startup
super.startInternal();
}
他调用了其父类的 startInternal()
@Override
protected synchronized void startInternal() throws LifecycleException {
// Start our subordinate components, if any
logger = 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 any
Container 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 any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
setState(LifecycleState.STARTING);
// Start our thread
if (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)));
}
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 ,其监听器处理逻辑也很简单,只是记录一下操作日志
欢迎指出我的错误!