• 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会对进行业务逻辑处理。

    细化流程:

  • 相关阅读:
    兔子数
    忠诚
    mysql字段名与关键字冲突(near "to":syntax error)
    C/C++使用心得:enum与int的相互转换
    ubuntu重新安装 apache2
    ubuntu 删除mysql
    Notepad++ 代码格式化
    linux文件字符集转换(utf8-gb2312)
    字符编码详解——彻底理解掌握编码知识,“乱码”不复存在
    c语言判断是否是utf8字符串,计算字符个数
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/13202001.html
Copyright © 2020-2023  润新知