1. 程式人生 > 實用技巧 >Tomcat原始碼分析(2)-聯結器Connector整體架構

Tomcat原始碼分析(2)-聯結器Connector整體架構

上一篇博文中,主要分析了tomcat的整體架構,通過上一篇的分析可以知道,tomcat主要有兩部分組成,分別為聯結器(Connector)和容器(Container)。本文介紹聯結器(Connector)。

一、Connector的主要功能

聯結器主要用於對外交流,它負責接收外部的請求,然後把請求轉交給container進行處理。主要功能如下:

  1. 監聽網路請求、接受位元組流
  2. 根據應用層協議(HTTP or AJP)把接受到位元組流轉換成TomcatRequest
  3. 把TomcatReqeust轉換成ServletRequest
  4. 呼叫容器Servlet,得到ServletResponse
  5. 把ServletRespone轉換成TomcatResponse
  6. 把TomcatResponse轉化成位元組流,返回給瀏覽器

基於以上詳細分析可知Connector的主要功能可以抽象為三點

  • 網路監聽
  • 協議解析處理
  • 協議遮蔽轉換(tomcatRequest到servletReqeust轉換,servletResponse到tomcatResponse的轉換)

二、Connetor內部的元件

基於上述的分析,接下來具體看tomcat connector的程式碼元件,主要有三個

  • Endpoint-用於網路監聽
  • Processor-用於協議解析處理
  • Adapter-用於轉換,解耦connector和container

tomcat的類設計中增加了一個ProtocolHandler, 把Endpoint和Processor,Adapter封裝到了一起。先看一個整體元件圖。

三、Endpoint介紹

Endpoint是通訊節點,實現了TCP/IP協議,包含兩個核心元件:

  1. Acceptor,主要用於監聽socket連結請求,
  2. 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會對進行業務邏輯處理。

四、細化流程