9

Tomcat 系列篇三-介绍下 Coyote

 11 months ago
source link: https://nicksxs.me/2023/09/24/Tomcat-%E7%B3%BB%E5%88%97%E7%AF%87%E4%B8%89-%E4%BB%8B%E7%BB%8D%E4%B8%8B-Coyote/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Tomcat 系列篇三-介绍下 Coyote

前面介绍了 connector,这里边还有个很重要的概念是 Coyote,真正将前面的 connector 跟后面的 container 做了连接,
org.apache.tomcat.util.net.AbstractEndpoint#createSocketProcessor 从这里开始
然后会调用到 org.apache.tomcat.util.net.NioEndpoint#createSocketProcessor

@Override
protected SocketProcessorBase<NioChannel> createSocketProcessor(
        SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
    return new SocketProcessor(socketWrapper, event);
}

里面实际的是 new 了
org.apache.tomcat.util.net.NioEndpoint.SocketProcessor#SocketProcessor

protected class SocketProcessor extends SocketProcessorBase<NioChannel> {

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

        @Override
        protected void doRun() {
            /*
             * Do not cache and re-use the value of socketWrapper.getSocket() in
             * this method. If the socket closes the value will be updated to
             * CLOSED_NIO_CHANNEL and the previous value potentially re-used for
             * a new connection. That can result in a stale cached value which
             * in turn can result in unintentionally closing currently active
             * connections.
             */
            Poller poller = NioEndpoint.this.poller;
            if (poller == null) {
                socketWrapper.close();

然后是 org.apache.tomcat.util.net.NioEndpoint.SocketProcessor#doRun 这里开始运行

protected void doRun() {
    /*
     * Do not cache and re-use the value of socketWrapper.getSocket() in
     * this method. If the socket closes the value will be updated to
     * CLOSED_NIO_CHANNEL and the previous value potentially re-used for
     * a new connection. That can result in a stale cached value which
     * in turn can result in unintentionally closing currently active
     * connections.
     */
    Poller poller = NioEndpoint.this.poller;
    if (poller == null) {
        socketWrapper.close();
        return;
    }

    try {
        int handshake = -1;
        try {
            if (socketWrapper.getSocket().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 = socketWrapper.getSocket().handshake(event == SocketEvent.OPEN_READ, event == SocketEvent.OPEN_WRITE);
                // 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) {
                state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
            } else {
                state = getHandler().process(socketWrapper, event);
            }
            if (state == SocketState.CLOSED) {
                poller.cancelledKey(getSelectionKey(), socketWrapper);
            }

org.apache.coyote.AbstractProtocol.ConnectionHandler#process 这个 getHandler 是哪个呢

public AbstractHttp11Protocol(AbstractEndpoint<S,?> endpoint) {
    super(endpoint);
    setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
    ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
    setHandler(cHandler);
    getEndpoint().setHandler(cHandler);
}

上面补充下这个 Handler,帮助后面的理解,而这个 connectionHandler 则是实现了 AbstractEndpoint.Handler

protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {

        private final AbstractProtocol<S> proto;
        private final RequestGroupInfo global = new RequestGroupInfo();
        private final AtomicLong registerCount = new AtomicLong(0);
        private final RecycledProcessors recycledProcessors = new RecycledProcessors(this);

        public ConnectionHandler(AbstractProtocol<S> proto) {
            this.proto = proto;
        }

        protected AbstractProtocol<S> getProtocol() {
            return proto;
        }

然后会继续寻找真实的 Processer

@Override
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
    if (getLog().isDebugEnabled()) {
        getLog().debug(sm.getString("abstractConnectionHandler.process",
                wrapper.getSocket(), status));
    }
    if (wrapper == null) {
        // Nothing to do. Socket has been closed.
        return SocketState.CLOSED;
    }

    S socket = wrapper.getSocket();

    Processor processor = (Processor) wrapper.getCurrentProcessor();
    if (getLog().isDebugEnabled()) {
        getLog().debug(sm.getString("abstractConnectionHandler.connectionsGet",
                processor, socket));
    }
    // 省略代码
    // 直到这里创建 processor
                    if (processor == null) {
            processor = getProtocol().createProcessor();
            register(processor);
            if (getLog().isDebugEnabled()) {
                getLog().debug(sm.getString("abstractConnectionHandler.processorCreate", processor));
            }
        }

也就是 org.apache.coyote.http11.AbstractHttp11Protocol#createProcessor

@Override
protected Processor createProcessor() {
    Http11Processor processor = new Http11Processor(this, adapter);
    return processor;
}

再往后就是调用 process 方法了,然后它是 Http11Processor 的抽象父类
org.apache.coyote.AbstractProcessorLight
会调用 org.apache.coyote.AbstractProcessorLight#process 来处理前面说的 socket
接着会跑到这

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

    SocketState state = SocketState.CLOSED;
    Iterator<DispatchType> dispatches = null;
    do {
        if (dispatches != null) {
            DispatchType nextDispatch = dispatches.next();
            if (getLog().isDebugEnabled()) {
                getLog().debug("Processing dispatch type: [" + nextDispatch + "]");
            }
            state = dispatch(nextDispatch.getSocketStatus());
            if (!dispatches.hasNext()) {
                state = checkForPipelinedData(state, socketWrapper);
            }
        } 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);
            state = checkForPipelinedData(state, socketWrapper);
        } else if (status == SocketEvent.OPEN_WRITE) {
            // Extra write event likely after async, ignore
            state = SocketState.LONG;
        } else if (status == SocketEvent.OPEN_READ) {
            state = service(socketWrapper);

接下去就是
org.apache.coyote.http11.Http11Processor#service
再就是调用coyote的 service 方法也就是 org.apache.catalina.connector.CoyoteAdapter#service
这里就会调用到


connector.getService().getContainer().getPipeline().getFirst().invoke(
                        request, response);
                    

然后进行 valve 串的执行到 org.apache.catalina.core.StandardWrapperValve#invoke
会调用

filterChain.doFilter
                            (request.getRequest(), response.getResponse());

就会执行 filter 链
最后到
org.apache.catalina.core.ApplicationFilterChain#internalDoFilter

servlet.service(request, response);

就到了 DispatcherServlet 处理的流程, 这样就和之前介绍 DispatcherServlet开始的请求处理接上了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK