https://blog.csdn.net/u012803274/article/details/104723613/
https://blog.csdn.net/ko0491/article/details/98222332
NioEndpoint:死循环 -> processKey(SelectionKey sk, NioSocketWrapper socketWrapper) ->
- AbstractEndpoint.processSocket(SocketWrapperBase
socketWrapper, xxx) -> executor.execute(SocketProcessor sc)提交任务到线程池
SocketProcessor:doRun() -> getHandler().process(socketWrapper, event) ->
- AbstractProtocol.process() -> processor.process() ->
- AbstractProcessorLight.process() -> service(socketWrapper)
Http11Processor:
- 继承关系:AbstractProcessorLight -> AbstractProcessor -> Http11Processor
- AbstractProcessor 构造中初始化 request 和 response
- Http11Processor.service() 使用 SocketWrapperBase 给 request 和 response 赋值
CoyoteAdapter:
StandardEngineValve -> StandardWrapperValve.invoke():
- servlet = wrapper.allocate();
- ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
- filterChain.doFilter(ServletRequest request, ServletResponse response)
- 分配 servlet,创建 filterChain,调用 doFilter
- 这里就是 Tomcat 和 Spring 的分水岭
ApplicationFilterChain.doFilter() -> internalDoFilter() -> servlet.service()
Servlet.service() -> HttpServlet.service() -> Spring-FrameworkServlet.service() -> Spring-DispatcherServlet.do.doService() -> doDispatcher()
整体流程:socket -> http(request、response) -> filter -> servlet -> handlerMapping -> intercept -> handlerAdapter -> controller -> viewResolver -> view
Valve:阀门
SpringBoot 中 Tomcat:
先绑定端口:
AbstractEndpoint.start():
然后启动 Acceptor 单线程:
Acceptor 线程在 ServerSocketChannelImpl.accept() 上阻塞着,等待客户端接入:
当有客户端连接,就会调用 endpoint.setSocketOptions() 封装
http-nio-8080-ClientPoller 线程:
NioEndpoint$Poller:events() -> PollerEvent.run()
- SocketChannel 中注册读事件,并将 NioSocketWrapper(SocketWrapperBase) attch 到 SelectionKey
NioEndpoint$Poller:NioSocketWrapper key.attachment() -> processKey(sk, socketWrapper)
NioEndpoint$Poller 即负责绑定事件和 attch,还负责 selector.selectedKeys() 和 attachment()
线程:
- Acceptor:
- BlockPoller:
- ClientPoller:
- exec-x:
main 线程:
AbstractEndpoint.start()
- bindWithCleanup():绑定端口并启动 ServerSocketChannel
- 启动 BlockPoller 线程
- startInternal():
- new Poller(),pollerThread:启动 ClientPoller 线程,daemon = false
- startAcceptorThread():启动 Acceptor 线程
main 线程执行完后,就退出了。由于有其他非 daemon 线程,所有 JVM 不会一起退出。
Accept.run():
- socket = endpoint.serverSocketAccept():阻塞等待,接受客户端连接
- serverSock.accept()
endpoint.setSocketOptions(socket):
events() -> PollerEvent.run():运行 events 中的 PollerEvent
- if (interestOps == OP_REGISTER)
- socket.getIOChannel().register(selector, OP_READ, socketWrapper)
- if (interestOps == OP_REGISTER)
- while selector.selectedKeys()
- NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment()
- processKey()
- timeout()
- timeout()/processKey() -> processSocket()
- processorCache != null : processorCache.pop()
- SocketProcessorBase sc = createSocketProcessor()
- new SocketProcessor()
- “exec-x”:executor.execute(SocketProcessorBase sc)
- SocketProcessor -> SocketProcessorBase -> Runnable
- SocketProcessorBase.run() -> SocketProcessor .doRun()
请求处理:
Acceptor:accept -> setSocketOptions -> :接受客户端连接
- bufhandler = new SocketBufferHandler()
- NioChannel channel = new NioChannel(bufhandler)
- channel.reset(socket, newWrapper):将原始的 SocketChannelImpl 包装
- NioSocketWrapper socketWrapper/newWrapper = new NioSocketWrapper(channel, this):
- socketWrapper -> channel
- poller.register(channel, socketWrapper):
- socketWrapper.interestOps(SelectionKey.OP_READ)
- events.offer(new PollerEvent(socket, OP_REGISTER)):创建 PollerEvent 并加入 events
ClientPoller:
- events() -> PollerEvent.run():轮询从 acceptor 添加的事件 events
- selector.selectedKeys().iterator():遍历新来的事件,处理 PollerEvent 时新注册的 key
- NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment():获取 socketWrapper
- processKey(sk, socketWrapper) -> processSocket():处理读事件
- SocketProcessorBase sc = createSocketProcessor() -> new SocketProcessor()
- “exec-x”:executor.execute(SocketProcessorBase sc):提交 processor 到 exec 线程池
SelectionKey:
- OP_READ:1 << 0,1
- OP_WRITE:1 << 2,100,4
- OP_CONNECT:1 << 3,1000,8
- OP_ACCEPT:1 << 4,10000,16
NioEndpoint.OP_REGISTER = 0x100,和 OP_WRITE 一样