20、Tomcat源码:tomcatsocket处理流程分析

第十七篇分析了tomcat socket处理的概览,这篇对流程进行梳理,达到分析到主流程和大概的处理逻辑,比如request和response的创建等后续分析请求处理需要解决的疑惑,后面分析请求处理的时候碰到的涉及到这篇的问题将持续更新这篇

十七篇分析了socket处理的主流程如下

NIOEndPoint.startInternal->Poller->NIOEndPoint.processKey->

NIOEndPoint.createSocketProcessor() 得到SocketProcessor 调用run->ConnectionHandler.process->Http11Processor.service->CoyoteAdapter.service(request, response);->connector.getService().getContainer().getPipeline().getFirst().invoke(request, response)

上面将NIO的处理和主流程即父类的处理流程混在一起,下面分析的时候会区分开来

1、 NIOEndPoint的processKey方法,是在Poller线程中selector.select()后处理socket的时候调用,这个是NIOEndPoint独有,下面是processKey的代码片段,可以看出后续会调用processSocket方法,除了processSocket外还有个方法processSendfile,这个方法后续再看;

protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
           …………..
                     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);
                            }
                        }
   ………………………..
        }

2、 AbstractEndPoint子类(例如NIOEndPoint)会调用到processSocket方法,processSocket方法是AbstractEndPoint中的方法,也就是说每个EndPoint的子类都会调用processSocket,目前为止主流程应该是:;

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法

下面是processSocket方法的代码片段,参数socketWrapper是SocketWrapperBase类实例,对于NIO来说就是NioSocketWrapper,S是NioChannel,就是说子类在调用processSocket方法的时候会传入相关的SocketWrapper,对于NIO来说是NioSocketWrapper.下面的逻辑会在缓存processorCache中取SocketProcessorBase,processorCache是在各子类的EndPoint中实例化,而SocketProcessorBase的子类在每个子类EndPoint中定义,是每个子类的内部类,以NIOEndPoint举例,下面是NioEndPoint中SocketProcessorBase子类SocketProcessor的定义片段,可以看到最后会调用到handler的process方法,还要注意一点就是processSocket会用server.xml配置的executor执行SocketProcessorBase,如果配置了的话(会有默认的),目前为止主流程应该是:

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法->子类EndPoint的createSocketProcessor方法创建SocketProcessorBase(每个子类不同,定义在子类的java文件中)->调用SocketProcessorBase子类的run方法(Executor或者直接调用)

public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        ………………..
     SocketProcessorBase<S> sc = processorCache.pop();
            if (sc == null) {
                sc = createSocketProcessor(socketWrapper, event);
            } else {
                sc.reset(socketWrapper, event);
            }
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
                executor.execute(sc);
            } else {
                sc.run();
            }
     ………………………
}

NioEndPoint中SocketProcessorBase子类片段:

protected class SocketProcessor extends SocketProcessorBase<NioChannel> {

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

        @Override
        protected void doRun() {
          ………………..
                        state = getHandler().process(socketWrapper, event);
                  ………………………………
                socketWrapper = null;
                event = null;
                //return to cache
                if (running && !paused) {
                    processorCache.push(this);
        ……………….
}

3、 SocketProcessorBase子类的doRun方法,以NioEndPoint举例(SocketProcessor),上面有SocketProcessordoRun方法的代码片段,可以看到会调用到Handler的process方法,这个Handler是顶级抽象接口,主流程的一个环节,它的实现类定义在AbstractProtocol中,是AbstractProtocol类的一个静态内部类ConnectionHandler,这个handler的实例是在Protocol创建EndPoint的时候设置进去的,下面是代码片段;

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

现在主流程应该是下面:

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法->子类EndPoint的createSocketProcessor方法创建SocketProcessorBase(每个子类不同,定义在子类的java文件中)->调用SocketProcessorBase子类的run方法(Executor或者直接调用)-> AbstractProtocol. ConnectionHandler的process(SocketWrapperBase wrapper, SocketEvent status)方法

ConnectionHandler process(细节待后面分析)方法,下面的代码片段是handler处理的主逻辑

………….
processor = getProtocol().createProcessor();
………..
processor.process(wrapper, status);
……………

getProtocol返回当前的protocol,上面是初始化时候的代码片段,会调用protocol的createProcessor方法,再调用proccessor的process方法,十七篇的时候画了uml继承图,对于NioEndPoint,getProtocol返回的应该是Http11NioProtocol,它的createProcessor方法返回的是Http11Processor,那么现在的主要流程是下面:

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法->子类EndPoint的createSocketProcessor方法创建SocketProcessorBase(每个子类不同,定义在子类的java文件中)->调用SocketProcessorBase子类的run方法(Executor或者直接调用)-> AbstractProtocol. ConnectionHandler的process(SocketWrapperBase wrapper, SocketEvent status)方法->调用Processor(NioEndPoint对应Http11NioProtocol, Http11NioProtocol初始化的时候创建NioEndPoint)的process方法

protocol UML

*\

processor UML

*

4、 processor的process方法,process方法是在父类AbstractProcessorLightimplementsProcessor中,下面是代码片段,下面的主要逻辑后面分析,但可以从代码中看出会调用,会根据状态的不同去调用子类实现的dispatch、service和asyncPostProcess方法,现在的主流程应该是下面:;

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法->子类EndPoint的createSocketProcessor方法创建SocketProcessorBase(每个子类不同,定义在子类的java文件中)->调用SocketProcessorBase子类的run方法(Executor或者直接调用)-> AbstractProtocol. ConnectionHandler的process(SocketWrapperBase wrapper, SocketEvent status)方法->调用Processor(NioEndPoint对应Http11NioProtocol, Http11NioProtocol初始化的时候创建NioEndPoint)的process方法->processor(NioEndPoint为例就是Http11Processor)子类实现的service等

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();
                state = dispatch(nextDispatch.getSocketStatus());
            } else if (status == SocketEvent.DISCONNECT) {
                
            } 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 {
                state = service(socketWrapper);
            }

            if (state != SocketState.CLOSED && isAsync()) {
                state = asyncPostProcess();
            }

            if (getLog().isDebugEnabled()) {
                getLog().debug("Socket: [" + socketWrapper +
                        "], Status in: [" + status +
                        "], State out: [" + state + "]");
            }
……………………..
        } while (state == SocketState.ASYNC_END ||
                dispatches != null && state != SocketState.CLOSED);

        return state;
}

5、 Processor子类(NioEndPoint举例就是Http11Processor)的process方法将调用Adapter的service方法等;

现在的主流程应该是下面:

StartInternal->EndPoint子类触发调用processSocket方法(对于NIOEndPoint就是Poller->processKey)->EndPoint父类的processSocket方法->子类EndPoint的createSocketProcessor方法创建SocketProcessorBase(每个子类不同,定义在子类的java文件中)->调用SocketProcessorBase子类的run方法(Executor或者直接调用)-> AbstractProtocol. ConnectionHandler的process(SocketWrapperBase wrapper, SocketEvent status)方法->调用Processor(NioEndPoint对应Http11NioProtocol, Http11NioProtocol初始化的时候创建NioEndPoint)的process方法->processor(NioEndPoint为例就是Http11Processor)子类实现的service等*adapter的service方法等->XXXValve

6、 更新的内容和问题;

Request和Response类都是在Processor的处理中创建,Processor子类中的Service方法中的while循环处理状态和AbstractProtocol类中的process方法while循环处理状态这里做个记录,这篇将tomcat的socket在十七篇概括的基础上大概具体的分析了一下,因为复杂性,这篇会随着后面tomcat的具体分析随时更新。

看了StandardXXXValve后的分析,因为代码复杂性的关系,现只做概要性的分析,Valve会跟随容器的层次关系依次调用,最后调用到的是StandardWrapperValve,这里会得到对应的Servlet和Chain处理请求,这里是请求最后的一环,如果是singleThreadModel的servlet,StandardWrapper会有一个servletPool,每个thread都创建一个servlet实例,默认是false的,所以一般写的servlet都要注意并发的处理,对这个只是简单的做个记录。

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: