https://blog.csdn.net/u012803274/article/details/104723613/
https://blog.csdn.net/ko0491/article/details/98222332

Tomcat 到 Spring 流程 - 图1
Tomcat 到 Spring 流程 - 图2

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():
image.png
image.png
image.png

image.png
然后启动 Acceptor 单线程:
image.png
image.png
Acceptor 线程在 ServerSocketChannelImpl.accept() 上阻塞着,等待客户端接入:
image.png
当有客户端连接,就会调用 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:

image.png

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):

    • poller.register(channel, socketWrapper)
      • events.offer(new PollerEvent())

        Poller.run():

  • events() -> PollerEvent.run():运行 events 中的 PollerEvent

    • if (interestOps == OP_REGISTER)
      • socket.getIOChannel().register(selector, OP_READ, socketWrapper)

  • 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 一样