Tomcat源码架构笔记(servlet请求处理链路篇)
在上一篇文章中,我们在debug模式下完整的跟踪程序走了一遍,对Tomcat start启动阶段所做的操作有了大概的了解。
这回,我们一起看看,Tomcat服务器接受到一个请求到处理这个请求之间经历了怎样的过程。
![](/usr/themes/waxy/img/loading.gif)
Servlet请求处理链路分析
- 一个servlet如何被tomcat处理的?
- servlet请求 -> 可以处理当前servlet请求的servlet实例 -> servlet.service()
![Servlet请求处理链路和URL的对应关系 Servlet请求处理链路和URL的对应关系](/usr/themes/waxy/img/loading.gif)
在上一篇文章中我们知道Acceptor线程主要负责监听Socket嵌套字请求,并将其转给sekector(选择器)。
而poller线程,则负责检查sekector(选择器)中是否有数据到来的channel,如果有就进行处理。
![NIO模型 NIO模型](/usr/themes/waxy/img/loading.gif)
所以Servlet请求处理链路中最重要的就是poller线程
,他负责控制这一系列的操作。
Servlet请求处理链路流程
![Poller线程 Poller线程](/usr/themes/waxy/img/loading.gif)
启动Poller线程和Acceptor线程
![NioEndpoint.startInternal() NioEndpoint.startInternal()](/usr/themes/waxy/img/loading.gif)
我们可以看到在启动Acceptor线程,监听Socket之前,startInternal()
方法先启动了Poller线程。
Poller类的核心方法就是run()
方法。
他来负责循环检查selector
中是否有事件就绪,并在数据可用的时候转给Worker线程。
![NioEndpoint类 Poller.run() ① NioEndpoint类 Poller.run() ①](/usr/themes/waxy/img/loading.gif)
![NioEndpoint类 Poller.run() ② NioEndpoint类 Poller.run() ②](/usr/themes/waxy/img/loading.gif)
处理Channel(可以理解为处理Socket)
![NioEndpoint类 Poller.processKey() NioEndpoint类 Poller.processKey()](/usr/themes/waxy/img/loading.gif)
处理Socket请求具体方法
当Socket传进processSocket()
方法中,先判断该Socket是否为空。
不为空,则开始在线程池中检查获取SocketProcessor
处理线程(如果线程池中没有,就创建一个)。
![AbstractEndpoint.processSocket() ① AbstractEndpoint.processSocket() ①](/usr/themes/waxy/img/loading.gif)
使用线程池技术执行SocketProcessor
处理线程。
![AbstractEndpoint.processSocket() ② AbstractEndpoint.processSocket() ②](/usr/themes/waxy/img/loading.gif)
其中核心处理方法就是该线程的run()
方法。
![SocketProcessorBase.run() SocketProcessorBase.run()](/usr/themes/waxy/img/loading.gif)
子类中doRun()
方法的逻辑,首先取出对象,并判断握手状态。
![NioEndpoint类 SocketProcessor.doRun() NioEndpoint类 SocketProcessor.doRun()](/usr/themes/waxy/img/loading.gif)
确定握手完成后,调用process()
方法进一步处理。
![NioEndpoint类 SocketProcessor.doRun() NioEndpoint类 SocketProcessor.doRun()](/usr/themes/waxy/img/loading.gif)
process方法
(Handler处理请求)
![AbstractProtocol.process() AbstractProtocol.process()](/usr/themes/waxy/img/loading.gif)
获取一个Processor(应用层协议)。
![AbstractProtocol.process() AbstractProtocol.process()](/usr/themes/waxy/img/loading.gif)
调用该Processor(应用层协议)处理请求。
![AbstractProtocol.process() AbstractProtocol.process()](/usr/themes/waxy/img/loading.gif)
HttpProcessor进行内容请求解析
![AbstractProcessorLight.process() AbstractProcessorLight.process()](/usr/themes/waxy/img/loading.gif)
READ读状态处理(分支处理)
![AbstractProcessorLight.process() AbstractProcessorLight.process()](/usr/themes/waxy/img/loading.gif)
应用层处理器HttpProcessor对请求进行解析处理
![Http11Processor.service() Http11Processor.service()](/usr/themes/waxy/img/loading.gif)
解析封装原生Request/Response
完成之后,要传入Adapter适配(由Adapter继续处理Request/Response
)
![Http11Processor.service() Http11Processor.service()](/usr/themes/waxy/img/loading.gif)
CoyoteAdapter需要将Request/Response
进一步封装为HttpServletRequest/HttpServletResponse
![CoyoteAdapter.service() CoyoteAdapter.service()](/usr/themes/waxy/img/loading.gif)
根据URL找到可以处理该请求的对应组件(Mapper机制,详见下一节)
![CoyoteAdapter.service() CoyoteAdapter.service()](/usr/themes/waxy/img/loading.gif)
![CoyoteAdapter.postParseRequest() CoyoteAdapter.postParseRequest()](/usr/themes/waxy/img/loading.gif)
开始匹配
![Mapper.map() Mapper.map()](/usr/themes/waxy/img/loading.gif)
真正的匹配逻辑
![Mapper.internalMap() Mapper.internalMap()](/usr/themes/waxy/img/loading.gif)
request.getHost()
就是从刚才封装好的mapperData
中取出Host
![StandardEngineValve.invoke() StandardEngineValve.invoke()](/usr/themes/waxy/img/loading.gif)
![mapperData mapperData](/usr/themes/waxy/img/loading.gif)
![AbstractAccessLogValve.invoke() AbstractAccessLogValve.invoke()](/usr/themes/waxy/img/loading.gif)
![ErrorReportValve.invoke() ErrorReportValve.invoke()](/usr/themes/waxy/img/loading.gif)
Host中要去进一步把处理当前请求的Context取出来
![StandardHostValve.invoke() StandardHostValve.invoke()](/usr/themes/waxy/img/loading.gif)
把请求传递给context处理
![StandardHostValve.invoke() StandardHostValve.invoke()](/usr/themes/waxy/img/loading.gif)
![AuthenticatorBase.invoke() AuthenticatorBase.invoke()](/usr/themes/waxy/img/loading.gif)
寻找可以处理当前请求的wrapper
![StandardContextValve.invoke() StandardContextValve.invoke()](/usr/themes/waxy/img/loading.gif)
调用wrapper容器处理请求
![StandardContextValve.invoke() StandardContextValve.invoke()](/usr/themes/waxy/img/loading.gif)
寻找可以处理当前请求的Servlet
![StandardWrapperValve.invoke() StandardWrapperValve.invoke()](/usr/themes/waxy/img/loading.gif)
把能够处理当前请求的servlet示例从wrapper容器中取出来
![StandardWrapperValve.invoke() StandardWrapperValve.invoke()](/usr/themes/waxy/img/loading.gif)
为当前请求的处理生成一个过滤器链(在这个链路的核心逻辑要触发servlet调用)
![StandardWrapperValve.invoke() StandardWrapperValve.invoke()](/usr/themes/waxy/img/loading.gif)
执行过滤器链
![StandardWrapperValve.invoke() StandardWrapperValve.invoke()](/usr/themes/waxy/img/loading.gif)
过滤器链执行的核心方法
![ApplicationFilterChain.doFilter() ApplicationFilterChain.doFilter()](/usr/themes/waxy/img/loading.gif)
![ApplicationFilterChain.internalDoFilter() ApplicationFilterChain.internalDoFilter()](/usr/themes/waxy/img/loading.gif)
![控制台打印执行结果 控制台打印执行结果](/usr/themes/waxy/img/loading.gif)
Mapper组件体系结构
![Mapper组件体系结构 Mapper组件体系结构](/usr/themes/waxy/img/loading.gif)
Tomcat中使用了Mapper机制重新封装了Host -> Context -> Wrapper(Servlet)
之间的数据和关系。
![MapElement MapElement](/usr/themes/waxy/img/loading.gif)
在匹配出能够处理当前请求的Host -> Context -> Wrapper(Servlet)
,Mapper对象通过MapperListener.start();
来完成初始化好了。
![StandardService.startInternal() StandardService.startInternal()](/usr/themes/waxy/img/loading.gif)
StandardService -> StartInternal() -> MapperLintener.start()
中完成Mapper对象初始化。
注册Host
![MapperLintener.start() MapperLintener.start()](/usr/themes/waxy/img/loading.gif)
循环添加Host
![MapperLintener.registerHost() MapperLintener.registerHost()](/usr/themes/waxy/img/loading.gif)
此时,Mapper对象已经初始化完毕了
![Host Host](/usr/themes/waxy/img/loading.gif)
![Context Context](/usr/themes/waxy/img/loading.gif)
![Wrapper(Servlet) Wrapper(Servlet)](/usr/themes/waxy/img/loading.gif)
OK,至此Tomcat基本的初始化、启动、处理请求的过程已经梳理一遍了。
Tomcat通过套娃的设计,带来了层级分明的结构;
Tomcat通过统一的生命周期管理接口,让各个组件有序工作;
Tomcat通过使用多线程带来了效率与性能的提升;
正确的debug方式,可以轻松深入代码解决问题;