不可能通过一篇文章就学会源码。
tomcat使用了nio(nio基于channel和buffer,并且通过slector实现多路复用)。
一、初始化阶段
1)创建SocketServer并绑定到nio的channel中
2)Selector.open() 创建一个selector
3)将创建的selector放入一个线程中,这个线程不断循环扫描绑定的channel,如果channel中有数据,则读取数据进行处理
-
在NioEndPoint.Acceptor线程中,循环监听TCP的连接请求
图1 初始化ServerSocketChannel
图2 创建Selector
图3 把创建的Selector传入BlockPoller线程对象
图4 NioEndPoint.Acceptor监听TCP连接请求
二、接收请求阶段
1)如图4中,在接收到连接请求后,会开始进行处理
2)最终,将socket封装成PollerEvent,放入到events队列中
- 在 NioEndPoint.Poller线程中,循环读取events队列,执行元素中run()方法,将socket的读事件注册到selector上
3.1)如果selector读取到数据时,则启动一个线程开始处理
图5 将socket连接封装后放入events队列
图6 元素中的run()方法
图7 selector读取到数据,开始处理
图8 启动一个线程处理请求
三、线程处理请求阶段
继续上一节,现在看线程内部的处理流程。
处理请求的类是NioEndpoint.SocketProcessor
图9 NioEndpoint.SocketProcessor
图10 AbstractProtocol.ConnectionHandler
开始走入处理流(责任链模式)
图11 开始走入处理流
待验证问题:
1. request 如何匹配到context
2. tomcat责任链过滤器
已经找到可以处理请求的Context,并执行web应用自定义的过滤器
图12 自定义的过滤器
最后,进入到 org.springframework.web.servlet.DispatcherServlet
图13 DispatcherServlet