简单梳理一下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 容器级别。