上一节我们分析了容器的注册,现在我们继续分析tomcat的通信,如果没有通信,那么注册的容器就毫无用武之地,从StandardService的connector的启动开始

org.apache.catalina.core.StandardService.startInternal()

for (Connector connector: connectors) {
                try {
                    // If it has already failed, don't try and start it
                    if (connector.getState() != LifecycleState.FAILED) {
                        connector.start();
                    }
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connector), e);
                }
            }
        }

Connector的基类的start不再赘述,和其他的组件的基类是一样的,我们直接看到它实现的startInternal方法

protected void org.apache.catalina.connector.Connector.startInternal() throws LifecycleException {

        // Validate settings before starting
        if (getPort() < 0) {
            throw new LifecycleException(sm.getString(
                    "coyoteConnector.invalidPort", Integer.valueOf(getPort())));
        }
        //设置状态并且触发starting事件
        setState(LifecycleState.STARTING);

        try {
            //启动与当前连接器相关的协议处理程序
            protocolHandler.start();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
        }
    }

协议处理器的启动,在分析之前,我们先看下协议处理器的类图,这个类图我们在前面某些章节中就已经见过,这里再次看下

在这里插入图片描述

从类图中可以看到tomcat使用了桥接模式针对不同的协议实现了对应的协议处理器与(如果我们有需求的话,我们也可以针对自己设计的协议实现对应的处理器)不同类型的socket端点实现进行桥接,避免类膨胀。

public void org.apache.coyote.AbstractProtocol.start() throws Exception {
        if (getLog().isInfoEnabled()) {
            getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
        }
        //启动端点
        //(*1*)
        endpoint.start();

        // Start async timeout thread
        //启动异步超时线程
        asyncTimeout = new AsyncTimeout();
        Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
        int priority = endpoint.getThreadPriority();
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            priority = Thread.NORM_PRIORITY;
        }
        timeoutThread.setPriority(priority);
        timeoutThread.setDaemon(true);
        timeoutThread.start();
    }
    
    //(*1*)
    public final void org.apache.tomcat.util.net.AbstractEndpoint.start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            //绑定ip地址,端口
            bind();
            bindState = BindState.BOUND_ON_START;
        }
        //具体的启动逻辑
        startInternal();
    }

我们首先来看看tomcat是怎么绑定端口的,tomcat有NIO,NIO2,ARP(以前还有BIO)这几种端点实现,我们就挑选NIO进行分析吧

public void org.apache.tomcat.util.net.NioEndpoint.bind() throws Exception {
        //是否从stdin和stdout中获取用户指定的通道,默认false
        if (!getUseInheritedChannel()) {
            //打开通道
            serverSock = ServerSocketChannel.open();
            //给socket设置属性,比如backLog等
            socketProperties.setProperties(serverSock.socket());
            //绑定地址和设置最大可接受请求数
            InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
            serverSock.socket().bind(addr,getAcceptCount());
        } else {
            // Retrieve the channel provided by the OS
            Channel ic = System.inheritedChannel();
            if (ic instanceof ServerSocketChannel) {
                serverSock = (ServerSocketChannel) ic;
            }
            if (serverSock == null) {
                throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
            }
        }
        //设置为阻塞
        serverSock.configureBlocking(true); //mimic APR behavior

        // Initialize thread count defaults for acceptor, poller
        if (acceptorThreadCount == 0) {
            // FIXME: Doesn't seem to work that well with multiple accept threads
            //默认接收线程为1个,1个接收reactor
            acceptorThreadCount = 1;
        }
        if (pollerThreadCount <= 0) {
            //minimum one poller thread
            //轮询线程数,默认是电脑cpu个数,如果实在没有就设置为1个
            pollerThreadCount = 1;
        }
        //设置计数器
        setStopLatch(new CountDownLatch(pollerThreadCount));

        // Initialize SSL if needed
        //初始化ssl安全连接,我们使用的https就是这种
        initialiseSsl();
        //打开selector池,主要是为了创建共享Selector对象
        selectorPool.open();
    }

绑定好ip地址和端口之后,那么就应该启动接收线程了

public void org.apache.tomcat.util.net.NioEndpoint.startInternal() throws Exception {
        //如果还没有启动,那么进行启动
        if (!running) {
            //标记状态
            running = true;
            paused = false;
            //构建同步栈,第一个参数为默认大小,第二参数为配置的最大size限制
            //处理请求的处理器个数
            processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getProcessorCache());
            //事件个数
            eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                            socketProperties.getEventCache());
            //nio通道个数
            nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getBufferPool());

            // Create worker collection
            //获取线程池(可从Service中设置的线程池选择),如果为空,那么自己创建一个
            if ( getExecutor() == null ) {
                createExecutor();
            }
            //设置连接限制同步计数器(LimitLatch),默认个数10000
            initializeConnectionLatch();

            // Start poller threads
            //启动轮询器数组
            pollers = new Poller[getPollerThreadCount()];
            for (int i=0; i<pollers.length; i++) {
                pollers[i] = new Poller();
                Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
                pollerThread.setPriority(threadPriority);
                pollerThread.setDaemon(true);
                pollerThread.start();
            }
            //启动接收线程
            //(*1*)
            startAcceptorThreads();
        }
    }
    
    //(*1*)
    protected final void org.apache.tomcat.util.net.AbstractEndpoint.startAcceptorThreads() {
        //获取接收线程个数
        int count = getAcceptorThreadCount();
        acceptors = new Acceptor[count];

        for (int i = 0; i < count; i++) {
            acceptors[i] = createAcceptor();
            String threadName = getName() + "-Acceptor-" + i;
            acceptors[i].setThreadName(threadName);
            Thread t = new Thread(acceptors[i], threadName);
            t.setPriority(getAcceptorThreadPriority());
            t.setDaemon(getDaemon());
            t.start();
        }
    }

从上面的代码中我们可以看到tomcat启动两类关于socket接收的线程组,Acceptor线程组和Poller线程组

我们先来看下Acceptor的实现

 protected class org.apache.tomcat.util.net.NioEndpoint.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
                    //LimitLatch,如果接收的请求已经达到最大,那么会进行await
                    countUpOrAwaitConnection();

                    SocketChannel socket = null;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        //获取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
                    //配置socket,给socket设置属性,注册到轮询器中
                    if (running && !paused) {
                        // setSocketOptions() will hand the socket off to
                        // an appropriate processor if successful
                        //如果设置属性和注册失败,关闭这个socket
                        if (!setSocketOptions(socket)) {
                            closeSocket(socket);
                        }
                    } else {
                        //关闭socket
                        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.socket().close();
            } catch (IOException ioe)  {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("endpoint.err.close"), ioe);
                }
            }
            try {
                //关闭socket对象
                socket.close();
            } catch (IOException ioe) {
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("endpoint.err.close"), ioe);
                }
            }
        }
    }

当接收的Acceptor接收到请求后,获取到对应的socket,获取socket之后tomcat需要对它配置一些属性,并且注册到轮询器中

 protected boolean org.apache.tomcat.util.net.NioEndpoint.setSocketOptions(SocketChannel socket) {
        // Process the connection
        try {
            //disable blocking, APR style, we are gonna be polling it
            //配置为阻塞
            socket.configureBlocking(false);
            //获取对应的socket
            Socket sock = socket.socket();
            //配置属性
            socketProperties.setProperties(sock);
            //从nioChannels同步栈中弹出一个NioChannel(这里主要是为了避免每次创建NioChannel对象,从而节省性能,属于设计模式中的享元模式)
            //NioChannel是tomcat的包装类,用于包装JDK的socketChannel
            NioChannel channel = nioChannels.pop();
            //如果没有可复用的,创建新的
            if (channel == null) {
                //设置socket缓存处理器,读取缓冲,写缓冲,是否使用直接内存缓冲
                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 {
                //复用已经存在的NioChannel,直接设置其需要关联的socket
                //并且进行缓冲复位
                channel.setIOChannel(socket);
                channel.reset();
            }
            //tomcat采用轮询的策略获取轮询器,并将当前接收的通道注册到对应的轮询器的Selector中
            //(*1*)
            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;
    }
    
    //(*1*)
     public void org.apache.tomcat.util.net.NioEndpoint.Poller.register(final NioChannel socket) {
            //NioChannel引用是谁在处理它的请求
            socket.setPoller(this);
            //NioSocketWrapper 一个包装NioChannel与NioEndpoint端点对象的包装器
            NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
            //引用是谁包装了自己
            socket.setSocketWrapper(ka);
            //告诉包装器是谁在处理自己引用的通道
            ka.setPoller(this);
            //设置读写超时
            ka.setReadTimeout(getSocketProperties().getSoTimeout());
            ka.setWriteTimeout(getSocketProperties().getSoTimeout());
            ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
            ka.setSecure(isSSLEnabled());
            ka.setReadTimeout(getConnectionTimeout());
            ka.setWriteTimeout(getConnectionTimeout());
            PollerEvent r = eventCache.pop();
            //设置感兴趣的事件为读
            ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
            //构建当前将要发生的轮询事件,很明显当前的事件就是注册事件
            if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
            else r.reset(socket,ka,OP_REGISTER);//如果已经存在,那么重置为注册事件,这也是一种享元模式的使用
            //给轮询器添加事件,如果有必要的话会唤醒当前轮询器关联的selector,这样就可以从事件队列中获取事件进行处理
            //这里发生的是注册事件,唤醒之后就是注册通道
            addEvent(r);
        }

我们继续来看下轮询器的实现

public void org.apache.tomcat.util.net.NioEndpoint.Poller.run() {
            // Loop until destroy() is called
            while (true) {
                //是否存在事件的标记
                boolean hasEvents = false;

                try {
                    //轮询器是否已经关闭
                    if (!close) {
                        //判断是否存在需要处理的事件,并处理事件
                        //(*1*)
                        hasEvents = events();
                        //如果唤醒计数原先的数字大于零,那么可能已经需要处理的socket事件
                        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 {
                            //其他的情况,阻塞selectorTimeout毫秒
                            keyCount = selector.select(selectorTimeout);
                        }
                        //设置为零,表示无需立即处理socket事件
                        wakeupCounter.set(0);
                    }
                    if (close) {
                    
                        //如果轮询器被关闭,那么处理剩下的轮询器事件
                        events();
                        //超时处理,主要是关闭socket,注销selectionKey
                        timeout(0, false);
                        try {
                            //关闭selector
                            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
                //如果是在selector阻塞时被唤醒,那么优先处理事件
                if ( keyCount == 0 ) hasEvents = (hasEvents | events());
                //如果有感兴趣的事件发生,那么获取SelectionKey列表
                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
                    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();
        }
        
        
        //(*1*)
        public boolean events() {
            boolean result = false;

            PollerEvent pe = null;
            //循环事件列表
            for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) {
                result = true;
                try {
                    //调用事件的run方法,我们来看下我们在上面接口线程中接收的注册事件是怎么执行的。
                    //(*2*)
                    pe.run();
                    //复位,重置事件对象,用于复用
                    pe.reset();
                    if (running && !paused) {
                        //复用
                        eventCache.push(pe);
                    }
                } catch ( Throwable x ) {
                    log.error("",x);
                }
            }

            return result;
        }
        
        //(*2*)
        public void org.apache.tomcat.util.net.NioEndpoint.PollerEvent.run() {
            //如果是注册事件,那么进行给对应poller的selector注册读事件,设置附件为socketWrapper(socket包装器,持有NioChannel对象,缓冲处理器)
            if (interestOps == OP_REGISTER) {
                try {
                    socket.getIOChannel().register(
                            socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper);
                } catch (Exception x) {
                    log.error(sm.getString("endpoint.nio.registerFail"), x);
                }
            } else {
                //其他的事件,获取对应注册的SelectionKey对象
                final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
                try {
                    if (key == null) {
                        // The key was cancelled (e.g. due to socket closure)
                        // and removed from the selector while it was being
                        // processed. Count down the connections at this point
                        // since it won't have been counted down when the socket
                        // closed.
                        //如果为空,那么表示已经被注销,那么计数器减一
                        socket.socketWrapper.getEndpoint().countDownConnection();
                        ((NioSocketWrapper) socket.socketWrapper).closed = true;
                    } else {
                        final NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment();
                        //如果已经存在了,那么合并感兴趣的事件
                        if (socketWrapper != null) {
                            //we are registering the key to start with, reset the fairness counter.
                            int ops = key.interestOps() | interestOps;
                            socketWrapper.interestOps(ops);
                            key.interestOps(ops);
                        } else {
                            //其他的情况,注销这个key(key.cancel,当然还有其他的一些操作,比如socket的close等)
                            socket.getPoller().cancelledKey(key);
                        }
                    }
                } catch (CancelledKeyException ckx) {
                    try {
                        socket.getPoller().cancelledKey(key);
                    } catch (Exception ignore) {}
                }
            }
        }
        

当tomcat接收到请求时,tomcat是怎么处理他们的呢?

protected void org.apache.tomcat.util.net.NioEndpoint.Poller.processKey(SelectionKey sk, NioSocketWrapper attachment) {
            try {
                //如果已经关闭,那么注销当前key
                if ( close ) {
                    cancelledKey(sk);
                    //这个key是否有效,并且其附件不能为空,tomcat设置的附件是NioSocketWrapper对象
                } else if ( sk.isValid() && attachment != null ) {
                    //处理读与写事件
                    if (sk.isReadable() || sk.isWritable() ) {
                        //如果存在待发生的文件数据,那么处理发生文件
                        if ( attachment.getSendfileData() != null ) {
                            processSendfile(sk,attachment, false);
                        } else {
                            //大部分请求都是属于这个分支
                            //取消当前感兴趣的事件,这里就是sk.readyOps()读事件,对于http请求,它是没有状态的,
                            //处理一次就可以了
                            unreg(sk, attachment, sk.readyOps());
                            boolean closeSocket = false;
                            // Read goes before write
                            //处理读事件
                            if (sk.isReadable()) {
                                if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
                                    //处理不成功,标记关闭socket
                                    closeSocket = true;
                                }
                            }
                            //如果是写事件,那么处理写事件
                            if (!closeSocket && sk.isWritable()) {
                                if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
                                    closeSocket = true;
                                }
                            }
                            //注销这个key
                            if (closeSocket) {
                                cancelledKey(sk);
                            }
                        }
                    }
                } else {
                    //invalid key
                    //注销key
                    cancelledKey(sk);
                }
            } catch ( CancelledKeyException ckx ) {
                cancelledKey(sk);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error("",t);
            }
        }

处理socket中的数据

//socketWrapper, event:读或写事件,dispatch:使用线程池处理
public boolean org.apache.tomcat.util.net.AbstractEndpoint.processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        try {
            if (socketWrapper == null) {
                return false;
            }
            //享元模式
            SocketProcessorBase<S> sc = processorCache.pop();
            if (sc == null) {
                //如果没有,那么创建一个,用于维护socketWrapper与对应事件的关系
                sc = createSocketProcessor(socketWrapper, event);
            } else {
                sc.reset(socketWrapper, event);
            }
            //获取线程池
            Executor executor = getExecutor();
            //如果设置了使用线程池处理,并且存在线程池,那么就通过线程池处理
            if (dispatch && executor != null) {
                executor.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;
    }

既然SocketProcessorBase可以直接提交给线程池,那么这个类要么实现了Runnable,Callable,继承了Thread

public final void run() {
        synchronized (socketWrapper) {
            if (socketWrapper.isClosed()) {
                return;
            }
            doRun();
        }
    }


    protected abstract void doRun();

SocketProcessorBase是一个抽象模板类,在不同的端点中它有不同的实现了,我们研究的是NIO,所以我们就分析NIO的实现即可。

protected void org.apache.tomcat.util.net.NioEndpoint.SocketProcessor.doRun() {
            //从包装器中获取NioChannel
            NioChannel socket = socketWrapper.getSocket();
            //获取感兴趣的key
            SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());

            try {
                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());
                            //读事件
                            event = SocketEvent.OPEN_READ;
                        }
                    }
                } catch (IOException x) {
                    handshake = -1;
                    if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);
                } catch (CancelledKeyException ckx) {
                    handshake = -1;
                }
                //如果握手成功,处理socket
                if (handshake == 0) {
                    SocketState state = SocketState.OPEN;
                    // Process the request from this socket
                    //处理socket
                    if (event == null) {
                        state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
                    } else {
                        state = getHandler().process(socketWrapper, event);
                    }
                    //请求完毕后,如果状态被设置为SocketState.CLOSED,那么
                    //关闭socket,如果是长连接可能就不会那么早关闭了
                    if (state == SocketState.CLOSED) {
                        close(socket, key);
                    }
                //握手失败,关闭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);
                }
            }
        }
    }

根据socket事件分发处理


protected Processor org.apache.coyote.http11.AbstractHttp11Protocol.createProcessor() {
        //创建Http11Processor,这里大量的比如最大http请求头大小,等等都是AbstractHttp11Protocol的默认设置
        Http11Processor processor = new Http11Processor(getMaxHttpHeaderSize(),
                getAllowHostHeaderMismatch(), getRejectIllegalHeaderName(), getEndpoint(),
                getMaxTrailerSize(), allowedTrailerHeaders, getMaxExtensionSize(),
                getMaxSwallowSize(), httpUpgradeProtocols, getSendReasonPhrase(),
                relaxedPathChars, relaxedQueryChars);
        //获取适配器,这里获取的是CoyoteAdapter,这个适配器在Connector.initInternal初始化的时候设置的
        processor.setAdapter(getAdapter());
        //最大的长连接请求书
        processor.setMaxKeepAliveRequests(getMaxKeepAliveRequests());
        //上传超时时间
        processor.setConnectionUploadTimeout(getConnectionUploadTimeout());
        processor.setDisableUploadTimeout(getDisableUploadTimeout());
        //压缩最小大小,为了节省带宽,会对一些数据比较的进行压缩处理,但是这会消耗cpu,所以需要
        //设置触发压缩的最小大小
        processor.setCompressionMinSize(getCompressionMinSize());
        processor.setCompression(getCompression());
        processor.setNoCompressionUserAgents(getNoCompressionUserAgents());
        processor.setCompressibleMimeTypes(getCompressibleMimeTypes());
        processor.setRestrictedUserAgents(getRestrictedUserAgents());
        processor.setMaxSavePostSize(getMaxSavePostSize());
        processor.setServer(getServer());
        processor.setServerRemoveAppProvidedValues(getServerRemoveAppProvidedValues());
        return processor;
    }

public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
            throws IOException {

       。。。。。。省略代码
            } else if (status == SocketEvent.OPEN_READ){
                //处理Read事件,我们通常使用的就是这个
                state = service(socketWrapper);
            } 
            。。。。。。省略代码

        return state;
    }
    
    public SocketState org.apache.coyote.http11.Http11Processor.service(SocketWrapperBase<?> socketWrapper)
        throws IOException {
        //获取请求处理器,一个RequestInfo对象
        RequestInfo rp = request.getRequestProcessor();
        //设置当前请求处于解析阶段
        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);

        // Setting up the I/O
        //设置当前Http11Processor处理的socketWrapper对象
        setSocketWrapper(socketWrapper);
        //初始化输入缓冲,将配置的缓冲长度初始化ByteBuffer的初始化容量
        //这个配置我们在
        inputBuffer.init(socketWrapper);
        //初始化输出缓冲,将配置的缓冲长度初始化ByteBuffer的初始化容量
        outputBuffer.init(socketWrapper);

        // Flags
        keepAlive = true;
        openSocket = false;
        readComplete = true;
        boolean keptAlive = false;
        SendfileState sendfileState = SendfileState.DONE;
        
        while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
                sendfileState == SendfileState.DONE && !endpoint.isPaused()) {

            // Parsing the request header
            try {
                //解析http的请求头
                if (!inputBuffer.parseRequestLine(keptAlive)) {
                    if (inputBuffer.getParsingRequestLinePhase() == -1) {
                        return SocketState.UPGRADING;
                    } else if (handleIncompleteRequestLineRead()) {
                        break;
                    }
                }

                if (endpoint.isPaused()) {
                    // 503 - Service unavailable
                    response.setStatus(503);
                    setErrorState(ErrorState.CLOSE_CLEAN, null);
                } else {
                    keptAlive = true;
                    // Set this every time in case limit has been changed via JMX
                    request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
                    if (!inputBuffer.parseHeaders()) {
                        // We've read part of the request, don't recycle it
                        // instead associate it with the socket
                        openSocket = true;
                        readComplete = false;
                        break;
                    }
                    if (!disableUploadTimeout) {
                        socketWrapper.setReadTimeout(connectionUploadTimeout);
                    }
                }
            } catch (IOException e) {
                。。。。。。省略部分异常处理
            } 
            。。。。。。省略部分异常处理
            // Has an upgrade been requested?
            //获取请求头中Connection属性
            Enumeration<String> connectionValues = request.getMimeHeaders().values("Connection");
            boolean foundUpgrade = false;
            while (connectionValues.hasMoreElements() && !foundUpgrade) {
                foundUpgrade = connectionValues.nextElement().toLowerCase(
                        Locale.ENGLISH).contains("upgrade");
            }
            //如果找到upgrade属性
            if (foundUpgrade) {
                // Check the protocol
                //获取升级协议,比如websocket这种
                String requestedProtocol = request.getHeader("Upgrade");

                UpgradeProtocol upgradeProtocol = httpUpgradeProtocols.get(requestedProtocol);
                if (upgradeProtocol != null) {
                    if (upgradeProtocol.accept(request)) {
                        // TODO Figure out how to handle request bodies at this
                        // point.
                        response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
                        //设置升级响应头
                        response.setHeader("Connection", "Upgrade");
                        response.setHeader("Upgrade", requestedProtocol);
                        action(ActionCode.CLOSE,  null);
                        getAdapter().log(request, response, 0);

                        InternalHttpUpgradeHandler upgradeHandler =
                                upgradeProtocol.getInternalUpgradeHandler(
                                        getAdapter(), cloneRequest(request));
                        UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, null, null);
                        //响应客户端,发送协议升级http响应头
                        action(ActionCode.UPGRADE, upgradeToken);
                        return SocketState.UPGRADING;
                    }
                }
            }
            //如果没有发生错误,那么
            if (!getErrorState().isError()) {
                // Setting up filters, and parse some request headers
                rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
                try {
                    prepareRequest();
                } catch (Throwable t) {
                    。。。。。。处理错误
                }
            }

            if (maxKeepAliveRequests == 1) {
                keepAlive = false;
            } else if (maxKeepAliveRequests > 0 &&
                    socketWrapper.decrementKeepAlive() <= 0) {
                keepAlive = false;
            }

            // Process the request in the adapter
            if (!getErrorState().isError()) {
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    //处理请求
                    getAdapter().service(request, response);
            。。。。。。省略
    }
    

inputBuffer.parseRequestLine方法是具体读取socket中流信息的方法,根据http协议头进行解析,由于我们使用的NIO,所以不能一次性读取成功,tomcat会进行多次的读取,知道读取到完整的信息后停止读取,再进行下面的操作,具体的读取方式这里不做分析,首先说明一下几个类

  • MessageBytes 消息字节类,这个类一般用于描述所持有的消息类型,比如字节,字符,字符串等,内部还会关联数据块
  • AbstractChunk tomcat8.5中有两个实现ByteChunk和CharChunk,他们只维护对应数据的偏移位置,比如一个很长的字节数组,他们只做偏移指定某一个小块
public void org.apache.catalina.connector.CoyoteAdapter.service(org.apache.coyote.Request req, org.apache.coyote.Response res)
            throws Exception {
        //获取Request对象,这个request对象就是实现了HttpServletRequest的对象
        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);
        //如果为空,那么直接创建一个空的Request
        if (request == null) {
            // Create objects
            request = connector.createRequest();
            //将coyote的Request设置进去。这是一种适配器模式
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);

            // Link objects
            //互相关联
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            //设置notes,下次就可以直接从notes中获取
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            //设置查询字符串编码
            req.getParameters().setQueryStringCharset(connector.getURICharset());
        }

        if (connector.getXpoweredBy()) {
            response.addHeader("X-Powered-By", POWERED_BY);
        }

        boolean async = false;
        boolean postParseSuccess = false;

        req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());

        try {
            // Parse and set Catalina and configuration specific
            // request parameters
            //内部做了大量操作,比如从connector获取一些设置到coyoteRequest中,身份认证
            //解析session,是否能够找到context等等操作
            postParseSuccess = postParseRequest(req, request, res, response);
            if (postParseSuccess) {
                //check valves if we support async
                request.setAsyncSupported(
                        connector.getService().getContainer().getPipeline().isAsyncSupported());
                // Calling the container
                //调用Engine的排管,开始容器的调用
                connector.getService().getContainer().getPipeline().getFirst().invoke(
                        request, response);
            }
            。。。。。。省略request的异步操作

        } catch (IOException e) {
            // Ignore
        } finally {
           。。。。。。省略资源的释放,比如清除缓冲中数据等等
        }
    }

上面的connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);这段代码开始就是从engine-》host-》context-》wrapper,这部分内容我们留到下一节分析。