简单梳理一下Tomcat 的请求处理流程。Protocol 以Http11NioProtocol为例。
初始化
首先需要初始化 Connector 的各个组件
Connector.startInternal()
启动,同时启动Http11NioProtocol.start()
方法。ProtocolHandler.start()
启动Endpoint.start()
方法。NioEndpoint.start()
方法依次触发
2.1bind()
方法。开启并配置serverSock。serverSock=ServerSocketChannel.open()
2.2initializeConnectionLatch()
初始化ConnectionLatch, 默认连接上限10000
2.3 创建 Poller threads. poller threads个数默认等于CPU processor数
2.4startAcceptorThreads()
开启acceptor。acceptor 个数默认为 1。NioEnpoint.Acceptor
为一个Runnable. 在一个while loop 中accept 新的请求。
接受处理请求
接受请求
由Acceptor 接受请求
-
socket = serverSock.accept()
同步等待新请求 - 接受请求之后调用
setSocketOptions(SocketChannel)
处理 。
2.1 创建 NioChannel (或者从nioChannel 池中获取一个复用)
2.2 从Poller 池中获取一个 poller, 调用 register(channel) 向poller注册该channel。
处理请求
Connector 部分的处理
每个Poller 都对应一个 Selector。Poller 拥有一个 PollerEvent queue, 可以通过 PollerEvent 来向 selector 注册读/写事件。Poller.run() 每次循环会
1.1 检查执行 poller event queue 中的事件
1.2 调用selector.select 来获取读写事件,调用processKey(SelectionKey sk, NioSocketWrapper attachment)
进行处理
1.3 processKey() 检查 SelectionKey 中的就绪事件后,便将责任交给AbstractEndpoint.processSocket(SocketWrapperBase<S>, SocketEvent, boolean)
1.4 processSocket() 从池中取(或创建)SocketProcessor
和Executor
,使用Executor
执行SocketProcessor
1.5SocketProcessor
会handle SSL相关的操作,实际处理请求的部分又被转交给AbstractEndpoint.Handler<S>.process(SocketWrapperBase<S>, SocketEvent)
1.6SocketProcessor
将socketwrapper 转交给相应 protocol 实现的org.apache.coyote.Processor
子类进行处理。读写事件最终会传递给
org.apache.coyote.Processor
来进行处理, Http1.1对应的processor 为 Http11Processor。Http11Processor.service() 方法中会对请求进行解析,然后调用org.apache.coyote.Adapter
的service 方法将请求交给 container 处理CoyoteAdapter.service() 依次执行
3.1postParseRequest
调用Mapper
找到请求对应的Host, Context, Wrapper,存储在org.apache.catalina.connector.Request
以便后续使用
3.2connector.getService().getContainer().getPipeline().getFirst().invoke( request, response)
将请求请求传递给该Service
对应的Engine
的 pipeline 进行处理。
3.3 调用context.logAccess()
方法打log.logAccess()
方法末尾会调用 parentContainer 的logAccess()
方法,由此使得整条处理链路上的Container 都会打出log。
Container 部分的处理
Container 部分的处理由 valve pipeline 完成。
每个Container 对应一个 Pipeline
, pipeline 末端有一个 basic valve, 用来将请求传递给下一个valve.
调用Valve
的 invoke(Request request, Response response)
处理请求和调用下一个 valve。
StandardHostValve
获取Contextrequest.getContext()
, 调用 Context 的pipelinecontext.getPipeline().getFirst().invoke(request, response)
StandardContextValve
获取Wrapperrequest.getWrapper()
调用wrapper.getPipeline().getFirst().invoke(request, response)
StandardWrapperValve
的invoke
方法依次
3.1 调用wrapper.allocate()
创建/获取一个 servlet 实例
3.2 调用ApplicationFilterFactory.createFilterChain(request, wrapper, servlet)
创建 filter chain.
3.3 调用filter chainfilterChain.doFilter(request.getRequest(), response.getResponse())
3.4ApplicationFilterChain
在 filter chain 的末端,调用 servlet.service(req, resp)
Filter Chain
//Filter Chain
doFilter(ServletRequest request, ServletResponse response)
// Filter
doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
Filter Chain 的设计就决定了它并不是线程安全的。
每个请求都会创建一个FilterChain, 而ApplicationFilterChain
每次都会使用ApplicationFilterConfig.getFilter()
创建新的Filter 实例。
Filter 和 Valve 的作用很相似。不过Filter 是Servlet 级别的组件,作用范围在Servlet 级别。而Valve 则处在Tomcat 容器级别。