Tomcat NioEndpoint的SocketProcessor

功能简介

当Tomcat NioEndpoint中的poller线程监测到一个待处理的socket NIO事件时,它会将该事件委托给SocketProcessor在一个线程池或者当前线程完成相应的处理逻辑。

Socket NIO发生时从Poller到SocketProcessor的调用链

NioEndpoint$Poller.run()
	=> processkey()
		=> NioEndpoint父类AbstractEndpoint.processSocket()
		=> createSocketProcessor() // 创建SocketProcessor,随后在Worker线程池上执行其逻辑

AbstractEndpoint#processSocket源码分析

    /**
     *  AbstractEndpoint的方法processSocket() 	    
     * Process the given SocketWrapper with the given status. Used to trigger
     * processing as if the Poller (for those endpoints that have one)
     * selected the socket.
     *
     * @param socketWrapper The socket wrapper to process
     * @param event         The socket event to be processed
     * @param dispatch      Should the processing be performed on a new
     *                          container thread
     *
     * @return if processing was triggered successfully
     */
    public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        try {
            if (socketWrapper == null) {
                return false;
            }
            // 尝试循环利用之前回收的SocketProcessor对象,如果没有可回收利用的则
            // 创建新的SocketProcessor对象
            SocketProcessorBase<S> sc = processorCache.pop();
            if (sc == null) {
	            // 创建新的SocketProcessor对象
                sc = createSocketProcessor(socketWrapper, event);
            } else {
	            // 循环利用回收的SocketProcessor对象
                sc.reset(socketWrapper, event);
            }

			// 找到Worker线程池或者Worker线程
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
	            // 如果Worker线程池被设置并且被要求分发:dispatch==true,
	            // 则在Worker线程池上执行刚刚封装的SocketProcessor的设定逻辑
                executor.execute(sc);
            } else {
	            // 否则在当前线程上直接执行刚刚封装的SocketProcessor的设定逻辑
                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;
    }
	// NioEndpoint重写了父类AbstractEndpoint的方法createSocketProcessor
    @Override
    protected SocketProcessorBase<NioChannel> createSocketProcessor(
            SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
        return new SocketProcessor(socketWrapper, event);
    }

SocketProcessor 源码分析

    protected class SocketProcessor extends SocketProcessorBase<NioChannel> {

        public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
            super(socketWrapper, event);
        }

        @Override
        protected void doRun() {
        	// 该方法将会执行于 tomcat 的 worker 线程中,比如 : http-nio-8080-exec-1
        	// 获取待处理的客户端请求
            NioChannel socket = socketWrapper.getSocket();
            SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());

            try {
            	// 这里的 handshake 是用来处理 https 的握手过程的,
            	// 如果是 http 不需要该握手阶段,下面会将该标志设置为 0, 表示握手已经完成
                int handshake = -1;

                try {
                    if (key != null) {
                        if (socket.isHandshakeComplete()) {
                            // No TLS handshaking required. Let the handler
                            // process this socket / event combination.
                            handshake = 0;
                        } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||
                                event == SocketEvent.ERROR) {
                            // Unable to complete the TLS handshake. Treat it as
                            // if the handshake failed.
                            handshake = -1;
                        } else {
                            handshake = socket.handshake(key.isReadable(), key.isWritable());
                            // The handshake process reads/writes from/to the
                            // socket. status may therefore be OPEN_WRITE once
                            // the handshake completes. However, the handshake
                            // happens when the socket is opened so the status
                            // must always be OPEN_READ after it completes. It
                            // is OK to always set this as it is only used if
                            // the handshake completes.
                            event = SocketEvent.OPEN_READ;
                        }
                    }
                } catch (IOException x) {
                    handshake = -1;
                    if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);
                } catch (CancelledKeyException ckx) {
                    handshake = -1;
                }
                if (handshake == 0) {
                	// 处理握手完成或者不需要握手的情况
                    SocketState state = SocketState.OPEN;
                    // Process the request from this socket
                    if (event == null) {
	                    // 默认是读事件处理
	                    // 这里的getHandler()返回AbstractProtocol.ConnectionHandler,
	                    // 在Http11NioProtocol对象构造期间被创建并设置到当前NioEndpoint对象
                        state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
                    } else {
	                    // 响应指定事件处理
	                    // 这里的getHandler()返回AbstractProtocol.ConnectionHandler,
	                    // 在Http11NioProtocol对象构造期间被创建并设置到当前NioEndpoint对象	                    
                        state = getHandler().process(socketWrapper, event);
                    }
                    if (state == SocketState.CLOSED) {
                        close(socket, key);
                    }
                } else if (handshake == -1 ) {
                    close(socket, key);
                } else if (handshake == SelectionKey.OP_READ){
                    socketWrapper.registerReadInterest();
                } else if (handshake == SelectionKey.OP_WRITE){
                    socketWrapper.registerWriteInterest();
                }
            } catch (CancelledKeyException cx) {
                socket.getPoller().cancelledKey(key);
            } catch (VirtualMachineError vme) {
                ExceptionUtils.handleThrowable(vme);
            } catch (Throwable t) {
                log.error("", t);
                socket.getPoller().cancelledKey(key);
            } finally {
                socketWrapper = null;
                event = null;
                //return to cache
                if (running && !paused) {
                    processorCache.push(this);
                }
            }
        }
    }

SocketProcessor 的基类

public abstract class SocketProcessorBase<S> implements Runnable {

    protected SocketWrapperBase<S> socketWrapper;
    protected SocketEvent event;

    public SocketProcessorBase(SocketWrapperBase<S> socketWrapper, SocketEvent event) {
        reset(socketWrapper, event);
    }


    public void reset(SocketWrapperBase<S> socketWrapper, SocketEvent event) {
        Objects.requireNonNull(event);
        this.socketWrapper = socketWrapper;
        this.event = event;
    }


    @Override
    public final void run() {
        synchronized (socketWrapper) {
            // It is possible that processing may be triggered for read and
            // write at the same time. The sync above makes sure that processing
            // does not occur in parallel. The test below ensures that if the
            // first event to be processed results in the socket being closed,
            // the subsequent events are not processed.
            if (socketWrapper.isClosed()) {
                return;
            }
            doRun();
        }
    }


    protected abstract void doRun();
}

你可能感兴趣的:(Tomcat NioEndpoint的SocketProcessor)