http-nio-8088-Poller线程中在org.apache.tomcat.util.net.NioEndpoint.Poller#run这个函数里循环检测selector,若发现有SocketEvent.OPEN_READ事件则会将SelectionKey.attachment中的内容作为入参包装成runable,然后由org.apache.tomcat.util.threads.ThreadPoolExecutor执行任务。
这个runable的实现类是NioEndpoint$SocketProcessor,其中包含了catalina.Request coyote.Request等很多重要对象,还包含了很多HeapByteBuffer用于缓存http请求的字节流数据。详细层级结构如下
NioEndpoint$SocketProcessor
this$0:NioEndpoint
handler:AbstractProtocal$ConnectionHandler
recycledProcessors:AbstractProtocol$RecycledProcessors//缓存Http11Processor
- Http11Processor
inputBuffer:Http11InputBuffer
byteBuffer:HeapByteBuffer//org.apache.catalina.connector.InputBuffer#setByteBuffer中会将此处数据复制一份到下文的bb:HeapByteBuffer中
request:coyote
notes:Object[]
- Request
inputStream:CoyoteInputStream
ib:InputBuffer
bb:HeapByteBuffer//UTF8StreamJsonParser从此拿数据
applicationRequest:RequestFacade
socketWrapper:NioEndpoint$NioSocketWrapper
event:SocketEvent
线程池中的线程名类似为http-nio-8088-exec-2。在这个线程中会将从SelectionKey.attachment中获取字节流数据然后放到NioEndpoint$SocketProcessor的HeapByteBuffer中。然后后续的解析器依照HeapByteBuffer将字节流数据解析成对象。
在整个处理流程中,很少创建新对象,基本都是将从SelectionKey.attachment中获取到的数据内容更新到NioEndpoint#SocketProcessor已有的那些对象中。所以调试的时候,在很多对象的构造函数中加断点时断点都没法生效。因为这些对象早就已经构造好了。
为了提高资源使用率,每个runable的HeapByteBuffer中的byte数组其实都是同一个。
为了提高资源使用率,每个runable的org.apache.coyote.Request org.apache.catalina.connector.Request其实都是同一个(在org.apache.catalina.connector.CoyoteAdapter#service加断点可以看到这俩对象是同一个)。