Tomcat整体架构

Tomcat整体架构图

Tomcat是一个Servlet容器,在Tomcat中容器分为WrapperContextHostEngine。从Tomcat的server.xml中也可以看出他们的层级关系,Engine管理Host,Host管理Context,Context管理Wrapper,Wrapper管理Servlet,一个Tomcat一个Engine,一个Host表示一个虚拟主机,一个Engine下可以有多个,一个Context就是一个应用一个项目,Wrapper表示一个Servelet的包装,在定义Servelet时若没实现SingleThreadModel接口,则Tomcat中只会产生一个Servelet实例对象,若实现了该接口,则每个请求线程都会产生一个Servelet实例对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" maxKeepAliveRequests="2"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/HelloEleven" relaodable="false"docBase="E:\SourceCode\ElevenServlet\target\ElevenServlet"/>

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>
Pipeline

Pipeline是在每个容器中都会用到,而Pipeline中有一些列的Valve,这些Valve是真正处理相关逻辑的,在处理每个请求时,Tomcat就会调用具体配置的Valve,如上面的server.xml中的<Valve>标签。每个容易有默认的Valve,如Wrapper中:

1
2
3
4
5
6
public StandardWrapper() {
super();
swValve = new StandardWrapperValve();
pipeline.setBasic(swValve);
broadcaster = new NotificationBroadcasterSupport(); // 广播
}

自定义Valve:

1
2
3
4
5
6
7
8
9
10
11
public class TestValve extends RequestFilterValve {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
System.out.println("test value");
getNext().invoke(request, response);
}
@Override
protected Log getLog() {
return null;
}
}

使用时在server.xml中直接配置,每个容器都可以配置自己的Valve,也可以配置多个:

1
<Valve className="com.eleven.TestValve"/>

Tomcat生命周期

Tomcat架构是一种树状的层级管理结构,组件会有自己的父子节点每个节点都是组件,每个组件都有生命周期,为了管理方便,子节点的生命周期都是交由父节点来管理的

每个组件生命周期的管理主要由Lifecycle接口和LifecycleState枚举来表示,即每个组件都实现了Lifecycle类,Lifecycle接口定义了组件所有执行的动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface Lifecycle {
public static final String BEFORE_INIT_EVENT = "before_init";
public static final String AFTER_INIT_EVENT = "after_init";
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";

public void addLifecycleListener(LifecycleListener listener);

public LifecycleListener[] findLifecycleListeners();

public void removeLifecycleListener(LifecycleListener listener);

public void init() throws LifecycleException;

public void start() throws LifecycleException;

public void stop() throws LifecycleException;

public void destroy() throws LifecycleException;

public LifecycleState getState();

public String getStateName();

public interface SingleUse {
}
}

所有组件的所有生命周期状态LifecycleState枚举类来管理,第一个参数表示当前状态下组件是否可用,第二个参数表示当变为当前状态时出发相应事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null),
@Deprecated
MUST_STOP(true, null),
@Deprecated
MUST_DESTROY(false, null);

private final boolean available;
private final String lifecycleEvent;
private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}
public boolean isAvailable() {
return available;
}
public String getLifecycleEvent() {
return lifecycleEvent;
}
}

Tomcat生命周期流转

Tomcat生命周期的流转:

  • 所有状态都能转变为FAILED
  • 一个组件在STARTING_PREP、STARTING、STARTED状态调用start()方法不会产生影响
  • 一个组件在NEW状态调用start()方法时,会先调用init()方法
  • 一个组件在STOPPING_PREP、STOPPING、STOPPED状态调用stop方法不会产生影响
  • 一个组件在NEW状态调用stop()方法是,会将状态直接改为STOPPED。当组件自己启动失败去停止时,需要将子组件也进行停止,尽管某些子组件还没有启动。
  • 其他状态相互转换都会抛异常
  • 合法的状态转换发生时都会触发相应的LifecycleEvent事件,非合法的转换不会触发事件。

Tomcat事件监听

Tomcat中每个组件的状态会发送变化,变化的时候会抛出一些事件,Tomcat支持定义事件监听器监听并消费这些事件。实现事件监听功能的类为LifecycleBase每个组件都会继承该类。该类通过List<LifecycleListener> lifecycleListeners属性来保存事件监听器,即每个组件拥有一个事件监听器列表

所有组件的初始化开始停止销毁都是通过LifecycleBase中的方法来完成,具体的组件的具体的初始化、开始、停止、销毁逻辑都是通过实现相关的*Internal抽象方法来完成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
public abstract class LifecycleBase implements Lifecycle {
protected void fireLifecycleEvent(String type, Object data) {
lifecycle.fireLifecycleEvent(type, data);
}

public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners; // ContextCOnfig
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);
}

@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}

try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}


protected abstract void initInternal() throws LifecycleException;

@Override
public final synchronized void start() throws LifecycleException {
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
return;
}

if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}

try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}

protected abstract void startInternal() throws LifecycleException;

@Override
public final synchronized void stop() throws LifecycleException {

if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
}
return;
}
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
}
try {
if (state.equals(LifecycleState.FAILED)) {
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
stopInternal();
if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.AFTER_STOP_EVENT);
}
setStateInternal(LifecycleState.STOPPED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
} finally {
if (this instanceof Lifecycle.SingleUse) {
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}

protected abstract void stopInternal() throws LifecycleException;

@Override
public final synchronized void destroy() throws LifecycleException {
if (LifecycleState.FAILED.equals(state)) {
try {
stop();
} catch (LifecycleException e) {
log.error(sm.getString("lifecycleBase.destroyStopFail", toString()), e);
}
}

if (LifecycleState.DESTROYING.equals(state) || LifecycleState.DESTROYED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
} else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
}
return;
}
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
}
try {
setStateInternal(LifecycleState.DESTROYING, null, false);
destroyInternal();
setStateInternal(LifecycleState.DESTROYED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.destroyFail",toString()), t);
}
}
protected abstract void destroyInternal() throws LifecycleException;

private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException {
if (check) {
if (state == null) {
invalidTransition("null");
return;
}
if (!(state == LifecycleState.FAILED || (this.state == LifecycleState.STARTING_PREP && state == LifecycleState.STARTING) || (this.state == LifecycleState.STOPPING_PREP && state == LifecycleState.STOPPING) || (this.state == LifecycleState.FAILED && state == LifecycleState.STOPPING))) {
invalidTransition(state.name());
}
}
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
}

所有组件的状态的变更都是通过setStateInternal方法来完成的,从而调用fireLifecycleEvent方法来执行相关的监听器来完成相关的逻辑。

自定义监听器只需要实现LifecycleListener接口即可,定义好事件监听器后,每个组件就可以调用父类LifecycleBase中的addLifecycleListener()方法添加事件监听器到该组件的监听器列表中。虽然说是事件监听,但实际上并不是异步触发,而是主动调用事件监听器,从fireLifecycleEvent方法也可以很明显的看出。

1
2
3
public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}

Tomcat自定义类加载器

Tomcat 拥有不同的自定义类加载器,以实现对各种资源库的控制。一般来说Tomcat 主要用类加载器解决以下 4 个问题。

  • 同一个Tomcat中,各个Web应用之间各自使用的Java类库要互相隔离
  • 同一个Tomcat中,各个Web应用之间可以提供共享的Java类库。
  • 为了使Tomcat不受Web应用的影响,应该使服务器的类库与应用程序的类库互相独立
  • Tomcat支持热部署

在 Tomcat中,最重要的一个类加载器是Common类加载器,它的父类加载器是应用程序类加载器,负责加载$CATALINA_ BASE/lib$CATALINA_HOME/lib两个目录下所有的.class文件与.jar文件。

Tomcat中一般会有多个WebApp类加载器WebAppClassLoader,每个类加载器负责加载一个Web程序。它的父类加载器是Common类加载器

由于每个 Web 应用都有自己的 WebApp 类加载器,很好地使多个 Web 应用程序之间互相隔离且能通过创建新的WebApp类加载器达到热部署。这种类加载器结构能有效使Tomcat不受Web应用程序影响,而Common类加载器的存在使多个Web应用程序能够互相共享类库。