Tomcat总体结构
Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的“七寸”。下面是 Tomcat 的总体结构图:
从上图中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个 Container 可以选择对应多个 Connector。多个 Connector 和一个 Container 就形成了一个 Service,Service 的概念大家都很熟悉了,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了。所以整个 Tomcat 的生命周期由 Server 控制。
通过关键类来看Tomcat结构
Tomcat启动
当通过 ./startup.sh
脚本或直接通过 java
命令来启动 Bootstrap
时,Tomcat 的启动过程就正式开始了,启动的入口点就是 Bootstrap
类的 main
方法。
启动的过程分为三步,分别为:
1 | 1. Bootstrap初始化 |
bootstrap.init()
先贴出源码,在源码中标注了顺序,下面详解
1 | /** |
- Set Catalina path (设置catalina的路径信息)
- initClassLoaders(初始化三个ClassLoader)
- 设置Catalina的parentClassLoader
- 将catalinaDaemon赋值为Catalia实例
daemon.load(args)
贴出源码:
1 | /** |
可以看出这个做的主要事情是调用catalinaDaemon.load()
在第一步init的时候 知道catalinaDaemon为Catalina的实例,所以看下catalina.load(),其中的关键性代码如下:
1 | //1. Create and execute our Digester |
createStartDigester
添加规定的对象创建规则
为规定的对象添加设置属性规则
设置父级方法 完成后调用
举个例子:
1
2
3
4
5
6
7
8
9//添加规定的对象Server 对应Server.xml中的<Server>
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
//设置上级调用setServer方法 此处看下面的digester.push(this),将catalina的实例放入了栈顶,即会调用Catalina.setServer()指定了catalina中的server为parse时创建的Server对象
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");添加ruleSet
读取server.xml
重点步骤 digester.parse
1
2
3
4
5
6
7
8
9
10
11
121. getXMLReader().parse(input);
2. getXMLReader:getParser().getXMLReader();
3. getParser():getFactory().newSAXParser();
4. getFactory():SAXParserFactory.newInstance();
5. newInstance():FactoryFinder.find(
/* The default property name according to the JAXP spec */
SAXParserFactory.class,
/* The fallback implementation class name */
"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
可以得到第3步的getFactory()得到的实例为SAXParserFactoryImpl的实例
6. 第3步的newSAXParser():new SAXParserImpl(this, features, fSecureProcess); 得到的是SAXParserImpl()的实例 所以getParser()为SAXParserImpl
7. 最终调用的为:SAXParserImpl.parse(input)经过对xml文件的解析将会产生org.apache.catalina.core.StandardServer、org.apache.catalina.core.StandardService、org.apache.catalina.connector.Connector、org.apache.catalina.core.StandardEngine、org.apache.catalina.core.StandardHost、org.apache.catalina.core.StandardContext等等一系列对象,这些对象从前到后前一个包含后一个对象的引用(一对一或一对多的关系)。
调用server.init()
1
2
3setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);其中的重点方法为:initInternal(),initInternal()中的重点代码如下
1
2
3
4// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].init();
}同样的StandardService的init重点代码如下:
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//初始化container
if (container != null) {
container.init();
}
// 初始化Executor
for (Executor executor : findExecutors()) {
if (executor instanceof LifecycleMBeanBase) {
((LifecycleMBeanBase) executor).setDomain(getDomain());
}
executor.init();
}
// 初始化定义的Connector 在server.xml中的配置
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
connector.init();
} catch (Exception e) {
String message = sm.getString(
"standardService.connector.initFailed", connector);
log.error(message, e);
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw new LifecycleException(message);
}
}
}
直到service的初始化 我们可以发现 service的初始化中包含了container.init()和多个Connector.init()对应了上文中的一个service包含了一个container和多个connector
container是从哪里实例化的呢,在进行createStartDigester的时候 会添加多个RuleSet如:digester.addRuleSet(new EngineRuleSet("Server/Service/"));
打断点可以发现如下在digester中的rules包含了如下几个规则:1
2ObjectCreateRule[className=org.apache.catalina.core.StandardEngine, attributeName=className]
SetNextRule[methodName=setContainer, paramType=org.apache.catalina.Container]
在进行digester.parse()的时候就会对这些规则进行解析,将StandardEngine的实例绑定为Service的Container
通过代码可以看到StandardServer、StandardService、StandardEnginee、Connector均继承了抽象类LifecycleMBeanBase,抽象类实现了LifecycleBase接口。