承受申请:
当客户端发来新的申请后,Acceptor线程不再阻塞,会获取到socket,持续运行调用setSocketOptions():

  @Override    protected boolean setSocketOptions(SocketChannel socket) {        NioSocketWrapper socketWrapper = null;        try {            // Allocate channel and wrapper            NioChannel channel = null;            if (nioChannels != null) {                channel = nioChannels.pop();            }            if (channel == null) {                SocketBufferHandler bufhandler = new SocketBufferHandler(                        socketProperties.getAppReadBufSize(),                        socketProperties.getAppWriteBufSize(),                        socketProperties.getDirectBuffer());                if (isSSLEnabled()) {                    channel = new SecureNioChannel(bufhandler, this);                } else {                    channel = new NioChannel(bufhandler);                }            }            NioSocketWrapper newWrapper = new NioSocketWrapper(channel, this);            channel.reset(socket, newWrapper);            connections.put(socket, newWrapper);            socketWrapper = newWrapper;            // Set socket properties            // Disable blocking, polling will be used            socket.configureBlocking(false);// todo 每个socket是非阻塞式的            socketProperties.setProperties(socket.socket());            socketWrapper.setReadTimeout(getConnectionTimeout());            socketWrapper.setWriteTimeout(getConnectionTimeout());            socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());            // 将一个链接socket申请注册到poller中,而后应用异步io,解决读写事件            poller.register(socketWrapper);// 将申请的socket放在poller中开始轮询解决            return true;        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            try {                log.error(sm.getString("endpoint.socketOptionsError"), t);            } catch (Throwable tt) {                ExceptionUtils.handleThrowable(tt);            }            if (socketWrapper == null) {                destroySocket(socket);            }        }        // Tell to close the socket if needed        return false;    }

setSocketOptions正如办法名字,包装了一下此次客户端与服务端socket,
设置了socket的IO模式为非阻塞,我猜想这样的益处是,一旦建设好链接好,客户端能够发送多个读写事件,而不会阻塞。
在办法完结的中央,有一行很重要的办法poller.register(socketWrapper);
它负责利用NIO的形式,注册服务端感情趣味的可读事件(SelectionKey.OP_READ),不过这里并没有真正的进行注册,仅仅是封装成了Event,而后放在Poller的SynchronizedQueue队列中。

 private final SynchronizedQueue<PollerEvent> events = new SynchronizedQueue<>(); public void register(final NioSocketWrapper socketWrapper) {            socketWrapper.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.            PollerEvent pollerEvent = createPollerEvent(socketWrapper, OP_REGISTER);            addEvent(pollerEvent);        } private void addEvent(PollerEvent event) {            events.offer(event);            if (wakeupCounter.incrementAndGet() == 0) {                // 重点!!!事件注册好后,唤醒一次selector,进行解决,否则selector会阻塞                selector.wakeup();            }        }

当初是时候看看Poller这个线程在干什么事件了,间接看他的run();

   @Override        public void run() {            // Loop until destroy() is called            while (true) {                boolean hasEvents = false;                try {                    if (!close) {                        // 这里次要是解决register,每当有一个socket链接申请到来的时候                        // 每个socket须要注册本人感兴趣的工夫                        // 这里的socket申请起源是在Acceptor中                        // 也就是说Acceptor不停的往events队列中投放事件                        // poller不停的处理事件                        // 因而这里最重要的就是了解 每一个事件是什么                        // todo 要对这一块了解透彻,必须对非阻塞IO有十分深刻的理解                        // todo 再次加深了解                        hasEvents = events();                        // 每当有一个新的链接申请来的时候,都必须当初selector中注册本人感兴趣的事件                        // 这样当客户端发送事件后,才可能处理事件。                        // 然而,上面的select()只有当有事件来的时候,才会唤醒持续向下执行                        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;                    }                    // Either we timed out or we woke up, process events first                    if (keyCount == 0) {                        hasEvents = (hasEvents | events());                    }                } catch (Throwable x) {                    ExceptionUtils.handleThrowable(x);                    log.error(sm.getString("endpoint.nio.selectorLoopError"), x);                    continue;                }                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();                    iterator.remove();                    // attachment 怎么来的,是在注册的时候失去的。                    // todo 了解一下attachment工作原理                    NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();                    // Attachment may be null if another thread has called                    // cancelledKey()                    if (socketWrapper != null) {                        // sk次要用来判断事件的类型,事件的内容在附件中                        processKey(sk, socketWrapper);                    }                }                // Process timeouts                timeout(keyCount,hasEvents);            }            getStopLatch().countDown();        }

在每次循环中,先看看是否有新的申请链接利用NIO注册感兴趣的事件,如果有,那么就进行解决。如果没有就看看是否有IO事件,如果有则调用processKey()进行解决。
这里有一个疑难,为什么有了Acceptor还要有Poller呢?为什么不能在Acceptor中做这些事件。
Acceptor次要是负责链接的建设,那么谁来负责解决链接,另外,当链接好后,产生了读写事件了,该有谁来对立治理呢?Poller表演了这个角色。
第二个疑难是,为什么要在Poller中来实现真正的注册,而不是在Acceptor,要了解这一点必须要对NIO有肯定理解。在NIO中Selector的register()和select()都是阻塞式的,对于一个socke来说,必定式要register()再select()。先当初假如第一个客户端A发来链接申请,Poller因为在启动阶段线程就始终在运行了,然而因为没有事件产生,因而被阻塞在select()办法,此时尽管A客户端发来了申请,然而因为阻塞的起因,并不能注册胜利,没有注册胜利,天然也就没有读写事件,就这样始终期待着,那这样岂不死锁了?为了解决这个问题,才有addEvent()结尾处有一个唤醒的办法。

Poller循环中不仅负责老板交给的工作,还要分派任务,上面看下Poller如何解决Socket?Poller会通过NIO模型,当有IO事件到来时候,调用processKey()->processSocket()解决申请。而在processSocket()中,会把每个IO事件封装成SocketProcessorBase工作,交给wokers线程池执行。

    public boolean processSocket(SocketWrapperBase<S> socketWrapper,            SocketEvent event, boolean dispatch) {        try {            if (socketWrapper == null) {                return false;            }            SocketProcessorBase<S> sc = null;            if (processorCache != null) {                sc = processorCache.pop();            }            if (sc == null) {                sc = createSocketProcessor(socketWrapper, event);            } else {                sc.reset(socketWrapper, event);            }            // 留神这里的Executor,其实就是真正干活的workers            // workers的大小和一些信息,曾经在初始化的办法中对立做了,须要留神的是,应用linkQ作为阻塞队列。            // 那么这样的话,大量的申请如果不能及时处理,阻塞队列可能爆满,不能再执行新的工作,            // 因而tomcat会勾销此次读事件!!并且敞开socket链接            // 这里大略是这样的,每个socket链接建设好后,会有大量的读事件进行解决            // 因而这里委派给了workers线程池来解决            // 而咱们的具体的工作是后面的SocketProcessorBase 他是一个Runnable实现的对象            // 因而要看            Executor workers = getExecutor();            if (dispatch && workers != null) {                workers.execute(sc);            } else {                sc.run();            }        } catch (RejectedExecutionException ree) {            getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);            return false;        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            // This means we got an OOM or similar creating a thread, or that            // the pool and its queue are full            getLog().error(sm.getString("endpoint.process.fail"), t);            return false;        }        return true;    }

这里咱们能够把Acceptor了解咱们的老板,咱们TL就是那个接老板活的人(Poller),而后指定谁来干。嗯。。。。这里的"咱们",就是真正干活的workers。tomcat利用这三个组件,把相干的职责离开了,零碎更加清晰,也更加高效(两个线程),值得学习。另外也能够看到,Acceptor和Poller都是单线程,因为他们只分派任务,所以不存在性能瓶颈,而workers则必须以线程池的形式来运行了。所以在做零碎设计的时候,也要留神哪里才是最须要资源的中央。
woker工作内容:在后面,每个IO事件,被封装成SocketProcessorBase工作,交给线程池运行,因而咱们关注下SocketProcessorBase的run(),它会调用doRun()

  @Override        protected void doRun() {                  ...                if (handshake == 0) {                    SocketState state = SocketState.OPEN;                    // Process the request from this socket                    if (event == null) {                        state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);                    } else {                        state = getHandler().process(socketWrapper, event);                    }                    if (state == SocketState.CLOSED) {                        poller.cancelledKey(getSelectionKey(), socketWrapper);                    }                } else if (handshake == -1 ) {                    getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);                    poller.cancelledKey(getSelectionKey(), socketWrapper);                } else if (handshake == SelectionKey.OP_READ){                    socketWrapper.registerReadInterest();                } else if (handshake == SelectionKey.OP_WRITE){                    socketWrapper.registerWriteInterest();                }            } catch (CancelledKeyException cx) {                poller.cancelledKey(getSelectionKey(), socketWrapper);            } catch (VirtualMachineError vme) {                ExceptionUtils.handleThrowable(vme);            } catch (Throwable t) {                log.error(sm.getString("endpoint.processing.fail"), t);                poller.cancelledKey(getSelectionKey(), socketWrapper);            } finally {                socketWrapper = null;                event = null;                //return to cache                if (running && processorCache != null) {                    processorCache.push(this);                }                    }

办法省略了很多内容,外围看下getHandler().process(socketWrapper, event);这里获取到的Handler,就是在后面启动Connector创立的ConnectionHandler。ConnectionHandler解决的次要内容,依据具体协定
找到对应的Processor去解决这个socket。

Processor processor = (Processor) wrapper.takeCurrentProcessor();  if (processor == null) {                    // 依据咱们指定的协定,去创立对应的处理器                    processor = getProtocol().createProcessor();                    register(processor);                    if (getLog().isDebugEnabled()) {                        getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));                    }                }  // 依据具体协定去解决申请事件了                    state = processor.process(wrapper, status);

后面我在Connector启动的时候,创立了一个默认协定Http11NioProtocol,
因而getProtocol()返回Http11NioProtocol,而后通过它创立一个Processor,它会生成以Http11Processor。

 Http11Processor继承自AbstractProcessor public AbstractProcessor(AbstractEndpoint<?,?> endpoint) {        this(endpoint, new Request(), new Response());    }

上面看下Http11Processor是如何进行解决的,这里又用到了模板办法(Http11Processor继承自AbstractProcessorLight,实现了Processor接口):process->service();

   @Override    public SocketState service(SocketWrapperBase<?> socketWrapper)        throws IOException {getAdapter().service(request, response);

这里能够看到service的入参是SocketWrapperBase,数据被解析进了request,和response两个对象中。另外后面Connector启动的时候,也指定了适配器是,CoyoteAdapter,因而最终是调用在CoyoteAdapter.service(request, response).
到了这里咱们能够看到客户端发送数据后,服务端利用NIO收到可读事件,获取数据后,把内容转换成了request和response,而后利用适配器去解决。