Tomcat处理请求流程

- Connector组件的Acceptor监听客户端套接字连接并接收Socket。
 - 将连接交给线程池Executor处理,开始执行请求响应任务。
 - Processor组件读取消息报文,解析请求行、请求体、请求头,封装成Request对象。
 - Mapper组件根据请求行的URL值和请求头的Host值匹配由哪个Host容器、Context容器、Wrapper容器处理请求。
 - CoyoteAdaptor组件负责将Connector组件和Engine容器关联起来,把生成的Request对象和响应对象Response传递到Engine容器中,调用 Pipeline。
 - Engine容器的管道开始处理,管道中包含若干个Valve、每个Valve负责部分处理逻辑。执行完Valve后会执行基础的 Valve--StandardEngineValve,负责调用Host容器的Pipeline。
 - Host容器的管道开始处理,流程类似,最后执行 Context容器的Pipeline。
 - Context容器的管道开始处理,流程类似,最后执行 Wrapper容器的Pipeline。
 - Wrapper容器的管道开始处理,流程类似,最后执行 Wrapper容器对应的Servlet对象的 处理方法
 
Connector
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
 Connector用于接收请求并将请求封装成Request和Response来具体处理。最底层使用的是 Socket。Request和Response封装后交给Container(Servlet的容器)处理请求,Container处理后返回给Connector,最后由Socket返回给客户端。
结构
 Connector中具体是用 ProtocolHandler处理请求的,代表不同的连接类型。Http11Protocol使用普通Socket连接,Http11NioProtocol使用NioSocket连接。
 ProtocolHandler中有三个重要的组件:
- Endpoint:处理底层的Socket网络连接;
 - Processor:将Endpoint接收的Socket封装成Request;
 - Adapter:将封装后的Request交给Container处理;
 
 Endpoint的抽象类 AbstractEndpoint定义了 Acceptor和 AsyncTimeout两个内部类 和 Handler接口。
- Acceptor:监听请求;
 - AsyncTimeout:检查异步Request请求的超时;
 - Handler:处理接收的Socket,内部调用 Processor进行处理;
 
public class Connector extends LifecycleMBeanBase  {
    public Connector() { this(null); }
    public Connector(String protocol) {
        // 根据 server.xml 中 Connector 属性 protocol 的值找合适的 className
        // 此处返回  org.apache.coyote.http11.Http11NioProtocol
        // 赋值给  ProtocolHandler
        setProtocol(protocol);
        ProtocolHandler p = null;
        try {
            Class<?> clazz = Class.forName(protocolHandlerClassName);
            // 反射生成 Http11NioProtocol 时,在构造函数中 生成了 NioEndpoint。
            p = (ProtocolHandler) clazz.getConstructor().newInstance();
        } finally {
            this.protocolHandler = p;
        }
        // 设置编码集
        if (Globals.STRICT_SERVLET_COMPLIANCE) {
            uriCharset = StandardCharsets.ISO_8859_1;
        } else {
            uriCharset = StandardCharsets.UTF_8;
        }
    }
    // 初始化操作
    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        // 初始化是配置  CoyoteAdapter(Connector 作为参数)
        adapter = new CoyoteAdapter(this);
        // 协议处理器绑定 适配器
        protocolHandler.setAdapter(adapter);
        // 执行 协议处理器初始化操作
        protocolHandler.init();
    }
    // 使用此 连接器处理 请求
    @Override
    protected void startInternal() {
        // 验证端口
        if (getPort() < 0) { }
        // 设置生命周期状态值
        setState(LifecycleState.STARTING);
        // 调用 协议处理器 start 方法
        protocolHandler.start();
    }
}

Http11NioProtocol
 主要包含 NioEndpoint组件和 Http11NioProcessor组件。启动时由NioEndpoint组件启动端口监听,连接到来被注册到NioChannel队列中,由Poller轮询器负责检测Channel的读写事件,并在创建任务后放入线程池中,线程池进行任务处理。

public class Http11NioProtocol extends AbstractHttp11JsseProtocol<NioChannel> {
    // 创建了  NioEndpoint 类
    public Http11NioProtocol() {
        // 最终调用 AbstractProtocol 类
        super(new NioEndpoint());
    }
}
// 父类 AbstractProtocol
public abstract class AbstractProtocol implements ProtocolHandler,MBeanRegistration {
    @Override
    public void init() throws Exception {
        // endpointName---"http-nio-8080": http-nio  +  8080 组成。
        String endpointName = getName();
        // 去掉 双引号
        endpoint.setName(endpointName.substring(1, endpointName.length()-1));
        // domain ==  catalina
        endpoint.setDomain(domain);
        // Endpoint的初始化操作
        // serverSocketChannel 绑定端口
        endpoint.init();
    }
    @Override
    public void start() throws Exception {
        // Endpoint 的 start 方法,重点
        // 创建 Executor、最大连接、开启 Poller thread
        endpoint.start();
        // 异步超时 线程,
        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();
    }
}
// AsyncTimeout 实现 Runnable 接口
protected class AsyncTimeout implements Runnable {
    private volatile boolean asyncTimeoutRunning = true;
    // 后台线程检查异步请求并在没有活动时触发超时。
    @Override
    public void run() {
        // 死循环,直到接收到 shutdown 命令
        while (asyncTimeoutRunning) {
            Thread.sleep(1000);
            long now = System.currentTimeMillis();
            for (Processor processor : waitingProcessors) {
                processor.timeoutAsync(now);
            }
            // 循环,直到 Endpoint pause
            while (endpoint.isPaused() && asyncTimeoutRunning) {
                Thread.sleep(1000);
            }
        }
    }
}
NioEndpoint
 NioEndpoint是非阻塞IO的一个抽象,包含了:
- LimitLatch:连接数控制器。
 - Acceptor:套接字连接并注册到Channel队列中。
 - Poller:轮询检查事件列表。
 - SocketProcessor:任务定义器。
 - Executor:负责处理套接字。
 
// AbstractEndpoint
public void init() throws Exception {
    if (bindOnInit) {
        bind();
        bindState = BindState.BOUND_ON_INIT;
    }
}
public final void start() throws Exception {
    // 判断是否绑定过
    if (bindState == BindState.UNBOUND) {
        bind();
        bindState = BindState.BOUND_ON_START;
    }
    startInternal();
}
// NioEndpoint
@Override
public void bind() throws Exception {
	// 绑定 设置的端口
    if (!getUseInheritedChannel()) {
        serverSock = ServerSocketChannel.open();
        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;
        }
    }
    // 设置 阻塞模式
    serverSock.configureBlocking(true); //mimic APR behavior
    // 初始化 连接器、轮询器 默认线程数
    if (acceptorThreadCount == 0) {
        acceptorThreadCount = 1;
    }
    if (pollerThreadCount <= 0) {
        pollerThreadCount = 1;
    }
    setStopLatch(new CountDownLatch(pollerThreadCount));
    // 是否初始化 ssl
    initialiseSsl();
    selectorPool.open();
}
// 开启 NIO endpoint, 创建 acceptor, poller 线程.
@Override
public void startInternal() throws Exception {
	// 设置 running 状态
    if (!running) {
        running = true;
        paused = false;
        // 默认 DEFAULT_SIZE:128  500
        processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                                                 socketProperties.getProcessorCache());
        eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                                             socketProperties.getEventCache());
        nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                                              socketProperties.getBufferPool());
        if ( getExecutor() == null ) {
            createExecutor();
        }
		// 初始化 连接数控制器,默认最大连接数 10000
        initializeConnectionLatch();
        // 开启 poller 线程, 默认 2
        // 检测到 事件后,交给 processor 处理
        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();
        }
        // 开启 Acceptor 线程
        startAcceptorThreads();
    }
}
// AbstractEndpoint
protected final void startAcceptorThreads() {
    int count = getAcceptorThreadCount();
    acceptors = new Acceptor[count];
    // 开启 Acceptor 线程
    for (int i = 0; i < count; i++) {
        // NioEndpoint 中实现
        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();
    }
}
连接数控制器-------LimitLatch
处理流程图:


 NIO模式下,Tomcat默认把阀门大小设置为 10000,可在 server.xml Connector节点下配置 maxConnections 属性修改。在连接数到达最大值后,仍可以接收客户端连接,直到操作系统接收队列被塞满。默认100,可在 Connector节点下 配置 acceptCount 属性修改。
SocketChannel接收器--------Acceptor
 Acceptor主要监听是否有客户端发来的连接并接收该连接,accept操作是阻塞的。此时返回 SocketChannel对象。Acceptor接收 SocketChannel 对象后要把它设置成非阻塞(后面对客户端连接才去非阻塞模式处理),接着设置套接字属性,封装成非阻塞通道对象。(NioChannel--HTTP、SecureNioChannel--HTTPS),最后将非阻塞通道对象注册到通道队列由 Poller 负责检测事件。

// NioEndpoint
protected class Acceptor extends AbstractEndpoint.Acceptor {
    @Override
    public void run() {
        int errorDelay = 0;
        // 死循环,知道收到  shutdown 命令
        while (running) {
            // Loop if endpoint is paused
            while (paused && running) {
                state = AcceptorState.PAUSED;
                Thread.sleep(50);
            }
            if (!running) {
                break;
            }
            state = AcceptorState.RUNNING;
            try {
                // 超过最大 连接,等待状态
                countUpOrAwaitConnection();
                // 接收从server来的下一个socket连接
                SocketChannel socket = serverSock.accept();
                // 正确接收 socket,重置 errorDelay
                errorDelay = 0;
                // Configure the socket
                if (running && !paused) {
                    // 把 socket 交给合适的 处理器处理
                    if (!setSocketOptions(socket)) {
                        closeSocket(socket);
                    }
                } else {
                    closeSocket(socket);
                }
            }
        }
        state = AcceptorState.ENDED;
    }
}
protected boolean setSocketOptions(SocketChannel socket) {
    // 处理 socket
    try {
        // 设置 非阻塞模式
        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());
            // 判断是否开启 SSL 类型,生成不同类型的 Channel
            if (isSSLEnabled()) {
                channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
            } else {
                channel = new NioChannel(socket, bufhandler);
            }
        } else {
            channel.setIOChannel(socket);
            channel.reset();
        }
        // 获取 Poller,注册 成 Event 事件。
        getPoller0().register(channel);
    } catch (Throwable t) {
        // 出错了,就返回,进行 关闭 socket 处理
        return false;
    }
    return true;
}
轮询器----Poller
 需要同时对很多连接进行管理,通过不断遍历事件列表,对对应连接的相应事件作出处理。Poller内部依赖 JDK的Selector对象进行轮询,Selector会选择出待处理的事件,每轮询一次就选出若干需要处理的NioChannel,在NIO模式下,每次读取的数据时不确定的,每次读取的数据可能有请求头和请求行,每次只能尝试去解析报文,如果解析不成功则等待下次轮询读取更多数据后再次尝试,如果解析成功则做一些逻辑处理后对客户端响应,这些处理工作在任务定义器中定义。

// 在 NioEndpoint startInternal方法中
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();
}
// NioEndpoint 类中定义
public class Poller implements Runnable {
    private final SynchronizedQueue<PollerEvent> events =
        new SynchronizedQueue<>();
    private volatile boolean close = false;
    private Selector selector;
    @Override
    public void run() {
        // 死循环,直到调用 destory 法
        while (true) {
            boolean hasEvents = false;
            try {
                if (!close) {
                    // 在 Acceptor 收到请求封装成 Socket 注册到 event 中
                    // 在轮询时从Event中取,进行处理
                    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) {
                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();
                // 另一个线程调用了 cancelledKey 方法,attachment 可能为null
                // 移除次事件,否则进行处理事件
                if (attachment == null) {
                    iterator.remove();
                } else {
                    iterator.remove();
                    processKey(sk, attachment);
                }
            }
            // 处理超时情况
            timeout(keyCount,hasEvents);
        }
        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.isReadable()) {
                            // 在父类中定义
                            if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
                                closeSocket = true;
                            }
                        }
                        if (!closeSocket && sk.isWritable()) {
                            if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
                                closeSocket = true;
                            }
                        }
                        if (closeSocket) {
                            cancelledKey(sk);
                        }
                    }
                }
            } else {
                //invalid key
                cancelledKey(sk);
            }
        } catch ( CancelledKeyException ckx ) {
            cancelledKey(sk);
        }
    }
}
// AbstractEndpoint
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
                             SocketEvent event, boolean dispatch) {
    try {
        if (socketWrapper == null) {
            return false;
        }
        // 从 栈中取一个
        SocketProcessorBase<S> sc = processorCache.pop();
        if (sc == null) {
   			// 没有就新建一个
            sc = createSocketProcessor(socketWrapper, event);
        } else {
            sc.reset(socketWrapper, event);
        }
        // 判断是否有 Executor,最终都是调用 Processor 的 run方法。
        Executor executor = getExecutor();
        // 见SocketProcessor
        if (dispatch && executor != null) {
            executor.execute(sc);
        } else {
            sc.run();
        }
    } catch (RejectedExecutionException ree) {
        return false;
    }
    return true;
}
任务定义器---SocketProcessor
// 在上面的操作中,执行 run 方法时,
// SocketProcessorBase
@Override
public final void run() {
    synchronized (socketWrapper) {
        if (socketWrapper.isClosed()) {
            return;
        }
        doRun();
    }
}
// 在 NioEndpoint 类中实现
@Override
protected void doRun() {
    NioChannel socket = socketWrapper.getSocket();
    SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
    int handshake = -1;
    if (handshake == 0) {
        SocketState state = SocketState.OPEN;
        // 处理请求
        if (event == null) {
            // 调用 Handler 转交给 Processor 去处理 process 方法,
            state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
        } else {
            state = getHandler().process(socketWrapper, event);
        }
        if (state == SocketState.CLOSED) {
            close(socket, key);
        }
    }
    socketWrapper = null;
    event = null;
    //return to cache
    if (running && !paused) {
        processorCache.push(this);
    }
}
// AbstractProtocol
protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
    @Override
    public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
        if (wrapper == null) {
            return SocketState.CLOSED;
        }
        S socket = wrapper.getSocket();
        // 根据Socket获取具体协议的处理器
        Processor processor = connections.get(socket);
        // 如果process==null,尝试其它协议、新建等
        // SSL 支持
        processor.setSslSupport(
            wrapper.getSslSupport(getProtocol().getClientCertProvider()));
        // process 和 connection 关联
        connections.put(socket, processor);
        SocketState state = SocketState.CLOSED;
        do {
            // 处理
            state = processor.process(wrapper, status);
        } while ( state == SocketState.UPGRADING);
        // Make sure socket/processor is removed from the list of current
        connections.remove(socket);
        release(processor);
        return SocketState.CLOSED;
    }
}
// AbstractProcessorLight(公共父类)
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
    throws IOException {
    SocketState state = SocketState.CLOSED;
    Iterator<DispatchType> dispatches = null;
    do {
        // 根据 SocketEvent 所处的 状态执行不同操作。
        if (dispatches != null) {
            DispatchType nextDispatch = dispatches.next();
            state = dispatch(nextDispatch.getSocketStatus());
        } else if (status == SocketEvent.DISCONNECT) {
            // Do nothing here, just wait for it to get recycled
        } else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
            state = dispatch(status);
            if (state == SocketState.OPEN) {
                state = service(socketWrapper);
            }
        } else if (status == SocketEvent.OPEN_WRITE) {
            state = SocketState.LONG;
        } else if (status == SocketEvent.OPEN_READ){
            state = service(socketWrapper);
        } else {
            state = SocketState.CLOSED;
        }
        if (state != SocketState.CLOSED && isAsync()) {
            state = asyncPostProcess();
        }
        if (dispatches == null || !dispatches.hasNext()) {
            dispatches = getIteratorAndClearDispatches();
        }
    } while (state == SocketState.ASYNC_END ||
             dispatches != null && state != SocketState.CLOSED);
    return state;
}
// 调用具体协议的service方法处理请求
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper) {
    // 判断状态
    while (!getErrorState().isError() && keepAlive && !isAsync()
           && upgradeToken == null &&
           sendfileState == SendfileState.DONE && !endpoint.isPaused()) {
        // 解析request请求头
        try {
            if (!inputBuffer.parseRequestLine(keptAlive)) {
                if (inputBuffer.getParsingRequestLinePhase() == -1) {
                    return SocketState.UPGRADING;
                } else if (handleIncompleteRequestLineRead()) {
                    break;
                }
            }
            if (endpoint.isPaused()) {
                response.setStatus(503);
                setErrorState(ErrorState.CLOSE_CLEAN, null);
            } else {
                keptAlive = true;
                request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
                if (!inputBuffer.parseHeaders()) {
                    openSocket = true;
                    readComplete = false;
                    break;
                }
                if (!disableUploadTimeout) {
                    socketWrapper.setReadTimeout(connectionUploadTimeout);
                }
            }
        } catch (IOException e) {
            setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); break;
        } catch (Throwable t) {
            // 400 - Bad Request
            response.setStatus(400);
            setErrorState(ErrorState.CLOSE_CLEAN, t);
            // 日志调用处
            getAdapter().log(request, response, 0);
        }
        // Has an upgrade been requested?
        Enumeration<String> connectionValues = request.getMimeHeaders().values("Connection");
        boolean foundUpgrade = false;
        while (connectionValues.hasMoreElements() && !foundUpgrade) {
            foundUpgrade = connectionValues.nextElement().toLowerCase(
                Locale.ENGLISH).contains("upgrade");
        }
        if (foundUpgrade) {
            // Check the protocol
            String requestedProtocol = request.getHeader("Upgrade");
            UpgradeProtocol upgradeProtocol = httpUpgradeProtocols.get(requestedProtocol);
            if (upgradeProtocol != null) {
                if (upgradeProtocol.accept(request)) {
                    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);
                    action(ActionCode.UPGRADE, upgradeToken);
                    return SocketState.UPGRADING;
                }
            }
        }
        if (!getErrorState().isError()) {
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
            try {
                prepareRequest();
            } catch (Throwable t) {
                // 500 - Internal Server Error
                response.setStatus(500);
                setErrorState(ErrorState.CLOSE_CLEAN, t);
                getAdapter().log(request, response, 0);
            }
        }
        if (maxKeepAliveRequests == 1) {
            keepAlive = false;
        } else if (maxKeepAliveRequests > 0 &&
                   socketWrapper.decrementKeepAlive() <= 0) {
            keepAlive = false;
        }
        // 通过 CoyotAdapte 处理 request
        if (!getErrorState().isError()) {
            try {
                rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                // 处理 request,见 CoyoteAdapter 解析
                getAdapter().service(request, response);
                if(keepAlive && !getErrorState().isError() && !isAsync() &&
                   statusDropsConnection(response.getStatus())) {
                    setErrorState(ErrorState.CLOSE_CLEAN, null);
                }
            } catch (InterruptedIOException e) {
                setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
            } catch (HeadersTooLargeException e) {
                if (response.isCommitted()) {
                    setErrorState(ErrorState.CLOSE_NOW, e);
                } else {
                    response.reset();
                    response.setStatus(500);
                    setErrorState(ErrorState.CLOSE_CLEAN, e);
                    response.setHeader("Connection", "close");
                }
            } catch (Throwable t) {
                // 500 - Internal Server Error
                response.setStatus(500);
                setErrorState(ErrorState.CLOSE_CLEAN, t);
                getAdapter().log(request, response, 0);
            }
        }
        // Finish the handling of the request
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
        if (!isAsync()) {
            endRequest();
        }
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
        // If there was an error, make sure the request is counted as
        // and error, and update the statistics counter
        if (getErrorState().isError()) {
            response.setStatus(500);
        }
        if (!isAsync() || getErrorState().isError()) {
            request.updateCounters();
            if (getErrorState().isIoAllowed()) {
                inputBuffer.nextRequest();
                outputBuffer.nextRequest();
            }
        }
        if (!disableUploadTimeout) {
            int soTimeout = endpoint.getConnectionTimeout();
            if(soTimeout > 0) {
                socketWrapper.setReadTimeout(soTimeout);
            } else {
                socketWrapper.setReadTimeout(0);
            }
        }
        rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
        sendfileState = processSendfile(socketWrapper);
    }
    rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
}
CoyoteAdapter
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
	// request == null,新建并关联
    if (request == null) {
        // Create objects
        request = connector.createRequest();
        request.setCoyoteRequest(req);
        response = connector.createResponse();
        response.setCoyoteResponse(res);
        // Link objects
        request.setResponse(response);
        response.setRequest(request);
        // Set as notes
        req.setNote(ADAPTER_NOTES, request);
        res.setNote(ADAPTER_NOTES, response);
        // Set query string encoding
        req.getParameters().setQueryStringCharset(connector.getURICharset());
    }
	// 设置请求头,告知网站是用何种语言或框架编写的
    // 默认false,Servlet/4.0 JSP/2.3xxxxxxxxxxxxxx
    if (connector.getXpoweredBy()) {
        response.addHeader("X-Powered-By", POWERED_BY);
    }
    boolean async = false;
    boolean postParseSuccess = false;
    req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
    try {
        // 请求映射、解析参数等操作。
        postParseSuccess = postParseRequest(req, request, res, response);
        if (postParseSuccess) {
            //check valves if we support async
            request.setAsyncSupported(
                connector.getService()
                		.getContainer()
                		.getPipeline()
                		.isAsyncSupported());
            // 由 Pipeline 处理流程,见Pipeline篇
            connector.getService()
                		.getContainer()
                		.getPipeline()
                		.getFirst()
                		.invoke(request, response);
        }
        // 异步处理
        if (request.isAsync()) {
            // 省略
        } else {
            request.finishRequest();
            response.finishResponse();
        }
    } finally {
        // 处理访问日志,见日志篇
        if (!async && postParseSuccess) {
            Context context = request.getContext();
            if (context != null) {
                context.logAccess(request, response,
                     System.currentTimeMillis() - req.getStartTime(), false);
            }
        }
        req.getRequestProcessor().setWorkerThreadName(null);
        // 回收 request and response
        if (!async) {
            request.recycle();
            response.recycle();
        }
    }
}
												
											Tomcat处理请求流程的更多相关文章
- tomcat匹配请求流程(原创)
		
tomcat8.0.36 配置Connector属性allowTrace为true时,允许TRACE方法,默认禁止. tomcat8.0.36有一个BUG,该BUG在8.0.37里被修复,就是一个解析 ...
 - 6张图说清楚Tomcat原理及请求流程
		
前言 很多东西在时序图中体现的已经非常清楚了,没有必要再一步一步的作介绍,本文以图为主,然后对部分内容加以简单解释. 绘制图形使用的工具是 PlantUML + Visual Studio Code ...
 - 使用反向代理的http的请求流程
		
此文章主要为刚接触反向代理的小伙伴梳理请求流程,以便更好的理解反向代理是何时工作的 流程 由于浏览器是有缓存的,所以本地的hosts文件的信息也会在浏览器端缓存 当客户端发起一个新的请求(例如:输入的 ...
 - 如何安装部署和优化Tomcat?(Tomcat部署和优化与压测,虚拟主机配置,Tomcat处理请求的过程)
		
文章目录 前言 一:Tomcat安装部署 1.1:Tomcat简介 1.2:Tomcat核心组件 1.3:Tomcat处理请求的过程 1.3.1:请求过程基本解释 1.3.2:请求过程详细解释 1.4 ...
 - servlet单例模式以及servlet的请求流程
		
 目录 一.servlet 单例模式: 二.servlet的请求流程: ★ 流程: ★ 详细过程如下: 一.servlet 单例模式: tomcat服务器,通过Java的反射机制来自动调用servl ...
 - Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例
		
前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...
 - zookeeper源码分析之五服务端(集群leader)处理请求流程
		
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
 - ASP.NET MVC学前篇之请求流程
		
ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...
 - MVC视图请求流程视图
		
/* *视图请求流程 *当接受到home/index请求时 *先去找viewstart.cshtml视图,再去加载index.cshtml视图 ...
 
随机推荐
- Redis-概述
			
Redis支持的类型: String,List,Map,Set,Sorted set Redis的持久化: 1.Redis DataBase (RDB): RDB是在某个时间点将数据写入一个临时文件, ...
 - CNN中tensorboard数据可视化
			
1.CNN_my_test.py import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data ...
 - Tarjan系列1
			
tajan的dfs树系列算法: 求解割点,桥,强连通分量,点双联通分量,边双联通分量: tajan是一个dfs,把一个图变成一个dfs树结构, dfs树结构,本质是通过一个没有任何要求的dfs把图的边 ...
 - 手机浏览器的User-Agent汇总
			
手机浏览器的User-Agent汇总 之前介绍的 更简洁的方式修改Chrome的User Agent,轻松体验移动版网络这种简洁的方法好像只适用于Chrome, Chrome不只是浏览界面简洁,对应的 ...
 - WinSxS文件夹瘦身
			
WinSxS文件夹瘦身 2014-5-8 18:03:32来源:IT之家作者:阿象责编:阿象 评论:27 刚刚,我们分享了如何用DISM管理工具查看Win8.1 WinSxS文件夹实际大小.对于Win ...
 - VS2010 创建 windows service 程序
			
参考网上保护眼睛程序,自写程序如下. 1.创建一个名词为“CareEyeService”,类型为“WindowsService”的应用程序. 自动生成代码如下图: 2.修改ServiceCareEye ...
 - 搭建高可用mongodb集群(三)—— 深入副本集内部机制
			
在上一篇文章<搭建高可用mongodb集群(二)-- 副本集> 介绍了副本集的配置,这篇文章深入研究一下副本集的内部机制.还是带着副本集的问题来看吧! 副本集故障转移,主节点是如何选举的? ...
 - c# 设计模式 之:抽象工厂
			
1.作用:抽象工厂的目的就是生产[产品族],之前讲的“工厂模式”的每一个factory只造一种产品,抽象工厂让一个factory造多个产品. uml类图: 代码实现: 抽象工厂代码: namespac ...
 - 音乐mp4网站 汽车服务工程 张旭
 - Android studio ocr初级app开发问题汇总(含工程代码)
			
博客第一篇文章,稍作修改,增加文字介绍 开发目的 最近由于某些需求,需要在Android手机端实现OCR功能,大致为通过手机照相,识别出相片中的中文信息字段.但是由于新手光环+流程不熟悉,遇到了各种各 ...