设为首页 收藏本站
查看: 384|回复: 0

[经验分享] Tomcat学习1-架构与启动流程

[复制链接]

尚未签到

发表于 2017-1-28 16:05:46 | 显示全部楼层 |阅读模式
  一、Tomcat的启动流程与架构
  Tomcat启动的时候的debug的运行轨迹图,框出来的代表主要容器的执行方法。
  
DSC0000.gif
  Tomcat执行大致的流程图
DSC0001.png

  整体上看一看Tomcat的概览图
  
DSC0002.png
  
顶层元素:Server,Service

连接器元素:Connector(HTTP,AJP等)

容器元素:Engine(跟Connector结合,处理http请求),Host(对应于多个主机 i.e. mail.test.com,www.test.com,www.test2.com),Context(对应于一个个webapp应用),Wrapper(对应于一个个Servlet)

组件元素:Logger,Value ,Realm,Listener,Cluster等


  二、Tomcat启动的步骤:
  
 1. tomcat的启动从Bootstrap.main()开始-->init()-->start()。

Bootstrap
public void start()
throws Exception
{
.........
// Set Catalina path
setCatalinaHome();
setCatalinaBase();
//设置StandardClassLoader,加载${catalina.home}/lib,${catalina.home}/lib/*.jar
initClassLoaders();  
Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
.........
}

    2. Catalina.start().  
 

 


Catalina
public void start() {
.....
initDirs();
// 初始化JNDI名称
initNaming();
// 创建解析config/server.xml的规则
Digester digester = createStartDigester();
......
//正式解析。至此相关的Server->Service->Enginer->Host,
//也包括LifecycleListence、Connection等的实例和相关属性都组装配置完成
digester.push(this);
digester.parse(inputSource);
...........
// 启动server服务
if (getServer() instanceof Lifecycle) {
try {
((Lifecycle) getServer()).start();
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}
}
........
if (await) {
//阻塞在默认的8005端口,监听shutdown命令,来关闭tomcat
await();  // -->serverSocket.accept();  8005端口
stop();   //-->  ((Lifecycle) getServer()).stop();  
}
.........
}

 
 

  3. StandardServer.start() ,server启动。
 

 


StandardServer
public void start() throws LifecycleException {
.......
// 开启service,一个Server有多个Service,Service互相独立
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services instanceof Lifecycle)
((Lifecycle) services).start();
}
}
........
}

    4. StandardService.start(),Service启动

StandardService
public void start() throws LifecycleException {
.........
//初始化各种connection,在这里绑定tomcat需要的端口,或者抛出已绑定端口的异常
connectors.initialize();
..........
// 启动Enginer容器
if (container != null) {
synchronized (container) {
if (container instanceof Lifecycle) {
((Lifecycle) container).start();
}
}
}
......
// 但Enginer、Host、Context、Wrapper等容器都启动完成,那么启动connection,接受各种请求。
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
try {
((Lifecycle) connectors).start();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connectors), e);
}
}
}
.........
}

    5. Connector.start(),启动Connector;这步就是建立用户Socket,解析http请求,封装成request。最终request经过Engine->Host->Context->Wrapper等容器的Valve处理,在经过FilterChina的处理,最终由Servlet处理。

Connector
public void start() throws LifecycleException {
........
if( !initialized )
initialize();
//HTTP/1.1或AJP/1.3协议的处理器的启动,听见来自用户的请求Socket
protocolHandler.start();
........
}

   -----------------------------------------------------------------------------------------------------------
  下面步骤中的组件都是继承ContainerBase容器,看一下简略的关系图 
DSC0003.png

ContainerBase
public synchronized void start() throws LifecycleException {
// Validate and update our current component state
if (started) {
if(log.isInfoEnabled())
log.info(sm.getString("containerBase.alreadyStarted", logName()));
return;
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
// 启动各种组件,各种组件由server.xml、web.xml、context.xml等配置文件提供
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
logger = null;
getLogger();
if ((logger != null) && (logger instanceof Lifecycle))
((Lifecycle) logger).start();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
// 启动各种子容器Engine->Host->Context->Wrapper
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children instanceof Lifecycle)
((Lifecycle) children).start();
}
// 启动pipeline组件
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// 触发事件
lifecycle.fireLifecycleEvent(START_EVENT, null);
// Start our thread
threadStart();
// 触发事件
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
  -----------------------------------------------------------------------------------------------
  6. StandardEngine.start(),启动Engine;这步开始容器类的start

StandardEngine
public void start() throws LifecycleException {
if( started ) {
return;
}
if( !initialized ) {
init();
}
......
//一个Engine可以有多个Host,Host的启动
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children instanceof Lifecycle)
((Lifecycle) children).start();
}
.......
//启动各种组件和子容器start()
super.start();
.........
}

  7. StandardHost.start(),启动Host,

StandardHost
public void start() throws LifecycleException {
.........
//启动各种组件和子容器start()
super.start(); -->ContainerBase -->HostConfig
..........
//   目录webapps/
File appBase = appBase();
//  conf/Catalina/localhost目录
File configBase = configBase();
// 解析conf\Catalina\localhost\*.xml文件,对每个webapp生成一个context
HostConfig --> deployDescriptors(configBase, configBase.list());
// 部署WEBAPPS/目录下的WARs
HostConfig--> deployWARs(appBase, filteredAppPaths);
// Deploy expanded folders
HostConfig--> deployDirectories(appBase, filteredAppPaths);

}

     8. StandardContext .start(),启动Context,

StandardContext
public synchronized void start() throws LifecycleException {
............
//一个Context对应一个WebappLoader,也就是关联到了WebappClassLoader
//用于每个app下面的WEB-INF/classes和WEB-INF/lib类的加载
if (getLoader() == null) {
WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader);
}
...........
// 创建work目录,当做临时工作目录
//比如 \work\Catalina\localhost\host-manager
postWorkDirectory();
..............
//初始化classloader
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
..............
//初始化各种组件
if ((logger != null) && (logger instanceof Lifecycle))
((Lifecycle) logger).start();               
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
.............
//触发start事件
lifecycle.fireLifecycleEvent(START_EVENT, null);
//解析系统默认的 conf/web.xml文件,完成默认的filterChina、servlet的各种组装
ContextConfig --> defaultWebConfig();
//解析apps下的自定义 /WEB-INF/web.xml 文件,完成filterChina、servlet的各种组装
ContextConfig --> applicationWebConfig();
// 如果设置了 <load-on-startup>,则初始化Servlet,执行init()或servlet为jsp页面,则complile生成servlet文件,再init;
loadOnStartup(findChildren());
..........
}

  )
  9. StandardWrapper.start(),启动wrapper,standardWrapper就是Servlet的包装类

StandardWrapper
public void start() throws LifecycleException {
..........
//启动各种组件和子容器start()
super.start();
.........
//加载Servlet,此组件也就是Servlet的包装类,跟Servlet的关系通过此类
public synchronized void load() throws ServletException {
instance = loadServlet();
}
}
   --------------------------------------------------------------------------
  三、Tomcat的生命周期关键组件Lifecycle
  以上就是整个tomcat的启动过程,tomcat调用一个个组件的start(),父组件调用子组件start(),就这样一步步启动,直至整个tomcat启动完成。
  tomcat的启动与关闭的生命周期跟Lifecycle接口息息相关.
  图:Lifecycle接口的结构图
  
DSC0004.png
  图:Lifecycle的实现类
DSC0005.gif
  参考资料:
  http://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/(
Tomcat 系统架构与设计模式,第 1 部分: 工作原理

  http://www.ibm.com/developerworks/cn/java/j-lo-tomcat2/(Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-334625-1-1.html 上篇帖子: Tomcat 6中配置JNDI简单示例 下篇帖子: 【WEB】用Tomcat构建WEB站点
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表