Tomcat 架构设计
启动
org.apache.catalina.startup.Bootstrap#main()
-
org.apache.catalina.startup.Bootstrap#init()
- org.apache.catalina.startup.Bootstrap#initClassLoaders
- 创建三个
classLoader
, 名称分别为:common、server、shared
- 创建三个
- 设置当前线程上下文的classLoader -Thread.currentThread().setContextClassLoader(catalinaLoader)
- 设置当前线程上下文的classLoader -Thread.currentThread().setContextClassLoader(catalinaLoader)
- 反射调用org.apache.catalina.startup.Catalina#setParentClassLoader方法
- org.apache.catalina.startup.Bootstrap#initClassLoaders
-
设置标志位org.apache.catalina.startup.Bootstrap#setAwait(true)
-
执行org.apache.catalina.startup.Bootstrap#load()方法
-
反射调用org.apache.catalina.startup.Catalina.load()方法
-
初始化目录org.apache.catalina.startup.Catalina#initDirs
-
初始化命名org.apache.catalina.startup.Catalina#initNaming
-
创建digester,用于解析xml文件。org.apache.catalina.startup.Catalina#createStartDigester
-
解析web.xml文件
-
通过模板方法org.apache.catalina.util.LifecycleBase#init ,依次调用org.apache.catalina.core.StandardServer#initInternal
org.apache.catalina.core.StandardService#initInternal
- mapperListener.init(); -这个mapperListener具体还没看到是干什么的
- 会创建两个Connector:Connector[HTTP/1.1-8080]、Connector[AJP/1.3-8009]
- org.apache.catalina.connector.Connector#initInternal()
- 创建org.apache.catalina.connector.CoyoteAdapter
- 调用org.apache.coyote.http11.AbstractHttp11Protocol#init
- 调用org.apache.tomcat.util.net.AbstractEndpoint#init
org.apache.catalina.core.StandardEngine#initInternal
org.apache.catalina.core.ContainerBase#initInternal : 初始化线程池 startStopExecutor
-
-
-
调用org.apache.catalina.startup.Bootstrap#start方法
- 反射调用org.apache.catalina.startup.Catalina#start方法
- 通过模板方法org.apache.catalina.util.LifecycleBase#start
- 执行org.apache.catalina.core.StandardServer#startInternal
- 执行org.apache.catalina.core.StandardService#startInternal
- 执行org.apache.catalina.core.StandardEngine#startInternal
- 执行org.apache.catalina.core.StandardHost#startInternal
- 执行org.apache.catalina.core.StandardPipeline#startInternal
- 执行org.apache.catalina.core.ContainerBase#threadStart -启动用来定期检查会话超时的后台线程
- 执行org.apache.catalina.connector.Connector#startInternal
- 执行org.apache.coyote.AbstractProtocol#start
- 执行org.apache.tomcat.util.net.AbstractEndpoint#start
- 注册 shutdown hook
- 调用org.apache.catalina.core.StandardServer#await方法 : 为了阻塞主线程,让服务进入等待状态(用来监听HTTP请求的是守护线程)
- 通过模板方法org.apache.catalina.util.LifecycleBase#start
- 反射调用org.apache.catalina.startup.Catalina#start方法
Servlet/filter定义的获取
在start方法时进行事件的分发,调用org.apache.catalina.util.LifecycleBase#fireLifecycleEvent
- org.apache.catalina.startup.ContextConfig#lifecycleEvent
- org.apache.catalina.startup.ContextConfig#configureStart
- org.apache.catalina.startup.ContextConfig#webConfig -
- org.apache.tomcat.util.descriptor.web.WebXmlParser#parseWebXml(org.xml.sax.InputSource, org.apache.tomcat.util.descriptor.web.WebXml, boolean) : 解析Web.xml文件 ,并将解析后的信息保存在org.apache.tomcat.util.descriptor.web.WebXml实例中去(可以参考org.apache.tomcat.util.digester.Digester解析xml的过程- 使用Digester的push方法在Digester使用的stack中放置一个初始对象。在解析xml文件的过程中,Digester使用stack来保存它所找到的对象。第一个对象在遇到第一个标签时被放置到stack中,当最后一个标签处理完毕时被弹出。为了最后能检索到这个对象,会用一个初始对象来保留一个指向它的引用)
- 解析完毕之后会调用org.apache.catalina.startup.ContextConfig#configureContext方法将org.apache.tomcat.util.descriptor.web.WebXml对象中的信息设置到对象中去
- 比如org.apache.catalina.Context#setSessionTimeout
- 获取servlet的映射关系,关联到context对象中org.apache.catalina.Context#addServletMapping(java.lang.String, java.lang.String)
- 在servlet3.0+ 后,也可以用注解的方式
javax.servlet.annotation.WebServlet
,javax.servlet.annotation.WebFilter
代替web.xml文件中的配置,所以这些数据的来源除了要解析web.xml,还有对于注解配置的处理(从类中定义的注解获取servlet/filter的相关定义)- org.apache.catalina.startup.ContextConfig#processAnnotationWebServlet
- org.apache.catalina.startup.ContextConfig#processAnnotationWebFilter
- org.apache.catalina.startup.ContextConfig#webConfig -
- org.apache.catalina.startup.ContextConfig#configureStart
Servlet的实例化/初始化
-
org.apache.catalina.core.StandardContext#startInternal
-
org.apache.catalina.core.StandardContext#loadOnStartup -根据
load-on-startup
参数实例化所有需要在启动时加载的servlet-
org.apache.catalina.core.StandardWrapper#load
-
org.apache.catalina.core.StandardWrapper#loadServlet - 实例化(基于反射创建)
InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager(); servlet = (Servlet) instanceManager.newInstance(servletClass);
-
org.apache.catalina.core.StandardWrapper#initServlet - 初始化
-
-
-
Tomcat 接收解析HTTP请求
-
org.apache.catalina.connector.Connector#startInternal
-
org.apache.coyote.ProtocolHandler#start
-
org.apache.coyote.ProtocolHandler#start
-
org.apache.tomcat.util.net.AbstractEndpoint#start
-
org.apache.tomcat.util.net.NioEndpoint#startInternal
-
org.apache.tomcat.util.net.NioEndpoint.Acceptor#run
-
org.apache.tomcat.util.net.NioEndpoint.Poller#register
其中NioEndpoint中的Acceptor负责监听TCP/IP连接,并且通过调用run方法,将获取到的SocketChannel包装成Tomcat中的NioChannel,并注册到Tomcat 自己封装的轮训器Poller中
-
org.apache.tomcat.util.net.NioEndpoint.Poller#run - 轮训器。负责将套接字添加到轮询器的后台线程,检查轮询器是否有触发事件,并在事件发生时将关联的套接字交给适当的处理器。
-
调用org.apache.tomcat.util.net.NioEndpoint.Poller#processKey
-
调用org.apache.tomcat.util.net.NioEndpoint#processSocket
-
调用org.apache.tomcat.util.net.NioEndpoint.SocketProcessor#run - worker线程
-
调用org.apache.tomcat.util.net.AbstractEndpoint.Handler#process
-
调用org.apache.coyote.http11.Http11Processor#process - 处理HTTP请求。其中包括解析请求行:1.org.apache.coyote.http11.Http11InputBuffer#parseRequestLine
2.org.apache.coyote.http11.Http11InputBuffer#parseHeaders -解析请求头
3 org.apache.coyote.http11.Http11Processor#prepareRequest - 设置请求的过滤器
-
-
-
-
-
-
-
-
-
-
-
- 第一版写的比较粗糙,后续考虑再梳理下流程,使用ProcessOn 绘制流程图出来。
- 未完,待续。