tomcat源码剖析之总体印象[tomcat工作原理]

         上年末和今年前趁着空闲使用svn上去apache把tomcat源码checkout下来,目的就是了解了解tomcat的工作原理,方便以后开发项目,同时也可以研究一下里面的优雅代码和熟悉多线程等基础知识。选择TOMCAT_6_0_38转换成eclipse项目,通过几日的走读代码和一行行代码debug,得出了tomcat的整个运行过程——从启动tomcat到启动webapp项目,再到监听http请求然后处理http请求,由于tomcat系统设计复杂,博文长度有限,这篇文章着重说明tomcat启动运行过程,没有涉及到处理http的过程说明。换句话说就是tomcat内部各组件的运行关系,加上webapp项目启动运行过程,文章采用时序图来说明。

        tomcat运行过程大体上分为两部分,一部分为load,一部分为start,如图:

             tomcat整体运行过程时序图

通俗来讲就是初始化和运行,初始化部分根据tomcat的conf目录下的server.xml配置文件初始化tomcat各组件的实例对象,同时设置各组件实例的初始数据,初始化组件数据从顶层组件出发,StandardServer->StandardService->Connector->DefaultSocketFactory,各部分的初始数据设置完毕后,就进入运行阶段,各组件嵌套调用start方法,StandardServer->StandardService->StandardEngine->Connector,这里StandardEngine和Connector属于同一级组件,可以从server.xml配置文件看出来。engine组件启动顺序是StandardEngine->StandardHost->StandardContext;connector的启动顺序是Connector->Http11Protocol->JIoEndPoint,JIoEndPoint启动接收(Acceptor)线程,Acceptor没监听到一个socket连接,就会创建一个Worker线程进行处理。

        在tomcat初始化过程时序图如下:

                                                                   

在上图中的第4步createStartDigester获得一个digester实例,通过这个digester实例的parse可以根据config下的server.xml文件来创建和初始化组件实例,这里说一下Digester在解析web.xml项目文件的时候也会用到,digester是apache Commons下的一个子项目,需要深入研究从这里下http://commons.apache.org/proper/commons-digester/。第6步调用StandardServer的initialize方法触发StandardServer上面所有的init事件监听器,注册一个server元件(托管java对象)并使得它私有;调用StandardService的initialize方法的目的是激活预启动初始化,用于连接器Connector在unix操作环境下绑定受限制的端口;Connector的initialize方法目的是得到serversocket,Http11Protocol的init方法用来验证socket配置工厂的有效性;JIoEndPoint的init方法用于设置Acceptor的默认线程数,创建serversocket。层层嵌套实现预启动初始化。

        tomcat与启动初始化之后开始进入start启动阶段了,启动元件是嵌套进行的,start方法嵌套调用顺序由外及内是StandardServer->StandardService->StandardEngine和Connector,StandardServer的start方法里面首先触发standardserver元件before_start事件的所有LifecycleListeners,然后触发standardserver元件start事件的所有LifecycleListeners,然后调用StandardService的start方法,最后触发standardserver元件after_start事件的所有LifecycleListeners;StandardService的start方法类似StandardServer的start方法,首先触发StandardService元件的before_start事件的所有LifecycleListeners,然后触发StandardService元件的start事件的所有LifecycleListeners,然后先调用StandardEngine元件的start方法,调用executor的start方法,调用Connector的start方法,最后是触发StandardService元件的after_start事件的所有LifecycleListeners。在server.xml没有配置executor,所以下面着重介绍的是StandardEngine和Connector的start启动过程。

                                                                    tomcat的start运行过程时序图

         tomcat在StandardServer的start方法进入StandarEngine的start阶段,首先进入StandardEngine初始化方法init,init的目的是把engine托管起来,初始化StandardEngine之后,调用父类ContainerBase的start方法,ContainerBase的start方法首先是触发StandardEngine的before_start事件的所有LifecycleListeners,start方法获取到子元件StandardHost的实例,调用StandardHost的start方法,先调用自身init方法把StandardHost托管起来,再次调用父类ContainerBase的start方法,ContainerBase的start方法触发StandardHost元件的before_start事件的所有LifecycleListeners,然后获取到StandardHost的子元件StandardContext,调用StandardContext的start方法,调用StandardContext的init方法,到这里进入第8步,触发StandardContext元件的init事件的所有LifecycleListeners,回到StandardContext的start方法后触发StandardContext的before_start事件的所有LifecycleListeners,这里其中有一个是ContextConfig的LifecycleListeners是用来解析webapp项目文件web.xml的。StandardContext的start方法再往下走就进入了第9步resourceStart方法了,它是用来分配资源的,包括代理;第10步getCharsetMapper是用来初始化字符集映射器的,简单来讲就是创建字符集类实例,第11步postWorkDirectory使用指定创建工作目录的,就是通常我们在运行想的时候tomcat主目录下的work目录下面会创建catalina/localhost目录,这个目录是tomcat的缓存,保存tomcat运行过程中一些数据,例如session,编译过的jsp servlet等等;第12步调用webapploader的start方法,这个方法主要是运行webapploader组件,并且初始化相关联的class加载器,第13步调用StandardPipeline的start方法,里面分别触发了StandardPipeline元件的before_start事件、start事件、after_start事件,第14步之前把资源(resource)与context给关联起来,welcomefiles与context关联起来,然后第14步的mergeParameters是对server配置参数和项目配置web.xml的参数进行合并,第15步listenerStart方法配置该context的event listener实例集,并激活,第16步filterStart是配置应用filter并向filter发送消息,最后一个步骤loadOnStartup是加载并初始化所有启动时加载的servlet。

                                                                                          Container(start)运行时序图

        经过StandardEngine的start方法完成后,部署到上面的应用已经就绪了,也就是说就等请求过来了,于是connector开始工作(start)了,在第2步Connector的start方法的目的是通过该connector开始处理请求,里面首先是触发Connector组件的start事件的所有LifecycleListeners,把Http11Protocol组件托管起来,然后调用Http11Protocol的start方法,进入Http11Protocol的start方法后,把JIoEndPoint托管起来,调用JIoEndPoint的start方法,进入JIoEndPoint的start方法后,首先是创建worker线程栈,然后创建Acceptor线程,Acceptor线程主要是用来监听有没有socket连接上来,启用该Acceptor线程,在Acceptor的run方法里面调用了第5步的processSocket(socket),processSocket主要是把socket交给合适的processor(处理器)处理,在processSocket里面调用了第6步的getWorkerThread方法,里面调用createWorkerThread通过newWorkerThread维护worker栈,创建或分配worker线程,并且调用worker的start方法,第7步调用获取到的worker线程start方法,第8步把监听到的socket传入worker线程实例,第9步jvm会调用该worker线程的run方法,worker线程里面的run方法调用了第10步Http11ConnectionHandler的process方法,Http11ConnectionHandler的process方法是用来出来特定socket上面的请求的,然后process方法里面调用第11步Http11Processor的process方法,第11步之后就是复杂的http请求处理和生成响应的复杂处理了,这里不再叙述了,留在以后从开发webapp项目的角度剖析tomcat的时候会重点讲解。完成connector的start过程之后,进入第12步init,init是进行host、context、wrapper映射的,例如host与context的映射,context与welcomefile、resource的映射等等,



                                                                      图connector的start过程(以http为例)

        最后,推荐官网介绍tomcat体系结构网址http://tomcat.apache.org/tomcat-6.0-doc/architecture/startup.html,上面详细讲解了tomcat的3中运行方式的启动过程,有文本介绍方式,也有uml时序图方式。我已经努力减少文中错漏,也努力让博文阅读起来不费劲,但是如果有读者发现错漏,请指出,避免有人看到可能会让他误解,同时如果博客的读者阅读博客后觉得文中我的某些观点需要深入研究,欢迎你们一起来讨论,请给我一个向您学习的机会。渴望得到阅读过本博客的博友的响应——评论,请说出你阅读博客后的最真实感受

      

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值