tomcat coyote模块请求处理流程

以Http2.0协议,io方式为nio为例

时序图
在这里插入图片描述

  1. Connector启动时,启动其持有的EndPoint实例(NioEndPoint),EndPoint通过其持有的Acceptor轮询监听端口接收请求
 protected class Acceptor extends AbstractEndpoint.Acceptor {
   

        @Override
        public void run() {
   

            int errorDelay = 0;

            // Loop until we receive a shutdown command
            while (running) {
   

                // Loop if endpoint is paused
                while (paused && running) {
   
                    state = AcceptorState.PAUSED;
                    try {
   
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
   
                        // Ignore
                    }
                }

                if (!running) {
   
                    break;
                }
                state = AcceptorState.RUNNING;

                try {
   
                    //if we have reached max connections, wait
                    countUpOrAwaitConnection();

                    SocketChannel socket = null;
                    try {
   
                        // Accept the next incoming connection from the server
                        // socket
                        socket = serverSock.accept();
                    } catch (IOException ioe) {
   
                        // We didn't get a socket
                        countDownConnection();
                        if (running) {
   
                            // Introduce delay if necessary
                            errorDelay = handleExceptionWithDelay(errorDelay);
                            // re-throw
                            throw ioe;
                        } else {
   
                            break;
                        }
                    }
                    // Successful accept, reset the error delay
                    errorDelay = 0;

                    // Configure the socket
                    if (running && !paused) {
   
                        // setSocketOptions() will hand the socket off to
                        // an appropriate processor if successful
                        if (!setSocketOptions(socket)) {
   
                            closeSocket(socket);
                        }
                    } else {
   
                        closeSocket(socket);
                    }
                } catch (Throwable t) {
   
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }


        private void closeSocket(SocketChannel socket) {
   
            countDownConnection();
            try {
   
                socket.socket().close();
            } catch (IOException ioe)  {
   
                if (log.isDebugEnabled()) {
   
                    log.debug(sm.getString("endpoint.err.close"), ioe);
                }
            }
            try {
   
                socket.close();
            } catch (IOException ioe) {
   
                if (log.isDebugEnabled()) {
   
                    log.debug(sm.getString("endpoint.err.close"), ioe);
                }
            }
        }
    }
  1. 监听到请求后且socket状态为running,将channel注册到poller上,唤醒selector
 protected boolean setSocketOptions(SocketChannel socket) {
   
        // Process the connection
        try {
   
            //disable blocking, APR style, we are gonna be polling it
            socket.configureBlocking(false);
            Socket sock = socket.socket();
            socketProperties.setProperties(sock);

            NioChannel channel = nioChannels.pop();
            if (channel == null) {
   
                SocketBufferHandler bufhandler = new SocketBufferHandler(
                        socketProperties.getAppReadBufSize(),
                        socketProperties.getAppWriteBufSize(),
                        socketProperties.getDirectBuffer());
                if (isSSLEnabled()) {
   
                    channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
                } else {
   
                    channel = new NioChannel(socket, bufhandler);
                }
            } else {
   
                channel.setIOChannel(socket);
                channel.reset();
            }
            getPoller0().register(channel);
        } catch (Throwable t) {
   
            ExceptionUtils.handleThrowable(t);
            try {
   
                log.error("",t);
            } catch (Throwable tt) {
   
                ExceptionUtils.handleThrowable(tt);
            }
            // Tell to close the socket
            return false;
        }
        return true;
    }

 private void addEvent(PollerEvent event) {
   
	  events.offer(event);
	  if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();
}
  1. poller实现了Runnable,在run方法中使用selector轮询socket状态,当轮询到可处理的请求时调用processKey进行处理
 @Override
 public void run() {
   
     // Loop until destroy() is called
     while (true) {
   

         boolean hasEvents = false;

         try {
   
             if (!close) {
   
                 hasEvents = events();
                 if (wakeupCounter.getAndSet(-1) > 0) {
   
                     //if we are here, means we have other stuff to do
                     //do a non blocking select
                     keyCount = selector.selectNow();
                 } else {
   
                     keyCount = selector.select(selectorTimeout);
                 }
                 wakeupCounter.set(0);
             }
             if (close) {
   
                 events();
                 timeout(0, false);
                 try {
   
                     selector.close();
                 } catch (IOException ioe) {
   
                     log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
                 }
                 break;
             }
         } catch (Throwable x) {
   
             ExceptionUtils.handleThrowable(x);
             log.error("",x);
             continue;
         }
         //either we timed out or we woke up, process events first
         if ( keyCount == 0 ) hasEvents = (hasEvents | events());

         Iterator<SelectionKey> iterator =
             keyCount > 0 ? selector.selectedKeys().iterator() : null;
         // Walk through the collection of ready keys and dispatch
         // any active event.
         while (iterator != null && iterator.hasNext()) {
   
             SelectionKey sk = iterator.next();
             NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
             // Attachment may be null if another thread has called
             // cancelledKey()
             if (attachment == null) {
   
                 iterator.remove();
             } else {
   
                 iterator.remove();
                 processKey(sk, attachment);
             }
         }//while

         //process timeouts
         timeout(keyCount,hasEvents);
     }//while

     getStopLatch().countDown();
 }

protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
   
   try {
   
        if ( close ) {
   
            cancelledKey(sk);
        } else if ( sk.isValid() && attachment != null ) {
   
            if (sk.isReadable() || sk.isWritable() ) {
   
                if ( attachment.getSendfileData() != null ) {
   
                    processSendfile(sk,attachment, false);
                } else {
   
                    unreg(sk, attachment, sk.readyOps());
                    boolean closeSocket = false;
                    // Read goes before write
                    if (sk.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值