Tomcat源码之连接器Connector解析

Posted WK_BlogYard

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat源码之连接器Connector解析相关的知识,希望对你有一定的参考价值。

声明:本文摘抄参考自:https://www.cnblogs.com/Brake/p/13195737.html

Connector的主要功能:

  连接器主要用于对外交流,它负责接收外部的请求,然后把请求转交给container进行处理。主要功能如下:

  1.  监听网络请求、接受字节流
  2.  根据应用层协议(HTTP or AJP)把接受到字节流转换成TomcatRequest
  3.  把TomcatReqeust转换成ServletRequest
  4.  调用容器Servlet,得到ServletResponse
  5.  把ServletRespone转换成TomcatResponse
  6.  把TomcatResponse转化成字节流,返回给浏览器

  基于以上详细分析可知Connector的主要功能可以抽象为三点

  • 网络监听
  • 协议解析处理
  • 协议屏蔽转换(tomcatRequest到servletReqeust转换,servletResponse到tomcatResponse的转换)

Connector的内部组件

  tomcat connector的代码组件,主要有三个

  1. Endpoint-用于网络监听
  2. Processor-用于协议解析处理
  3. Adapter-用于转换,解耦connector和container

  tomcat的类设计中增加了一个ProtocolHandler, 把Endpoint和Processor,Adapter封装到了一起。先看一个整体组件图。

 EndPoint的介绍:

  Endpoint是通信节点,实现了TCP/IP协议,包含两个核心组件:

    Acceptor,主要用于监听socket链接请求,

    SocketProcessor,用于处理接收到的 Socket 请求,实现了runnable接口,在run方法中会调用processor对socket请求进行处理。

  Endpoint核心接口

public abstract class AbstractEndpoint<S> {

    protected Acceptor[] acceptors;

    protected abstract SocketProcessorBase<S> createSocketProcessor(
            SocketWrapperBase<S> socketWrapper, SocketEvent event);

    protected SynchronizedStack<SocketProcessorBase<S>> processorCache;
    /**
     * External Executor based thread pool.
     */
    private Executor executor = null;
}

  这里面还有一个Executor, 这个是tomcat自己扩展的线程池。Acceptor监听到socket请求后,创建SocketProcessor,由Executor来运行SocketProcessor。

  Acceptor核心代码:

protected class Acceptor extends AbstractEndpoint.Acceptor {
        @Override
        public void run() {
            while (running) {
                state = AcceptorState.RUNNING;
                try {
                    //Accept the next incoming connection from the server
                    SocketChannel socket = serverSock.accept();//监听请求
                    //setSocketOptions() will hand the socket off to an appropriate processor if successful
                    setSocketOptions(socket);//把请求传给SocketProcessor
                } catch (Throwable t) {

                }
            }
        }
    }

  setSocketOption最终会调用Endpoint的process方法。

  Endpoint的process核心方法代码如下:

public boolean processSocket(SocketWrapperBase<S> socketWrapper,
                                 SocketEvent event, boolean dispatch) {
        SocketProcessorBase<S> sc = processorCache.pop();
        if (sc == null) {
            sc = createSocketProcessor(socketWrapper, event);//创建SocketProcessor
        } else {
            sc.reset(socketWrapper, event);
        }
        Executor executor = getExecutor();
        executor.execute(sc);//交给线程池进行处理
        return true;
    }

  SocketProcessor的抽象类

public abstract class SocketProcessorBase<S> implements Runnable {

    protected SocketWrapperBase<S> socketWrapper;
    protected SocketEvent event;

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

    protected abstract void doRun();
}

  SocketProcessor类

protected class SocketProcessor extends SocketProcessorBase<NioChannel> {

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

        @Override
        protected void doRun() {
            NioChannel socket = socketWrapper.getSocket();
            SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
            getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
        }
    }

  上面类中getHandler().process的具体实现。(Handler的接口由Endpoint的内部类进行定义。

protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
        private final Map<S, Processor> connections = new ConcurrentHashMap<>();

        @Override
        public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {

            S socket = wrapper.getSocket();

            Processor processor = connections.get(socket);
            return processor.process(wrapper, status);
        }
    }

  至此、请求已经成功传给可processor。

Processor和Adapter

  Processor是应用层协议比如HTTP的处理。他负责把请求传给Adapter。核心代码如下。

@Override
    public SocketState service(SocketWrapperBase<?> socketWrapper)
            throws IOException {

        try {
            getAdapter().service(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

  adapter解耦了connector和container的关系,主要负责把tomcatRequest转换为servletRequest,然后最终调用container,核心代码如下.

public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
            throws Exception {
        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);
        if (request == null) {
            // Create objects
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);
        }
        // Calling the container
        connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
    }

  至此请求到达了container,我们的servlet会对进行业务逻辑处理。

细化流程:

 

以上是关于Tomcat源码之连接器Connector解析的主要内容,如果未能解决你的问题,请参考以下文章

tomcat8源码之架构解析

Tomcat连接器Connector源码解读架构概览,如何设计?为什么这样设计?

Tomcat连接器Connector源码解读架构概览,如何设计?为什么这样设计?

从连接器组件看Tomcat的线程模型——连接器简介

Tomcat 连接器 Connector 源码追踪

Tomcat源码分析 ----- HTTP请求处理过程