Tomcat源码解析——一次请求的处理流程

        在上一篇文章中,我们知道Tomcat在启动后,会在Connector中开启一个Acceptor(接收器)绑定线程然后用于监听socket的连接,那么当我们发出请求时,第一步也就是建立TCP连接,则会从Acceptor的run方法处进入。

Acceptor: 
       public void run() {
            int errorDelay = 0;
            //只有运行状态才进入while循环
            while (running) {
                while (paused && running) {
                    state = AcceptorState.PAUSED;
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                if (!running) {
                    break;
                }
                state = AcceptorState.RUNNING;

                try {
                    countUpOrAwaitConnection();

                    Socket socket = null;
                    try {
                        //阻塞接受TCP连接
                        socket = serverSocketFactory.acceptSocket(serverSocket);
                    } catch (IOException ioe) {
                        //...省略
                    }
                    errorDelay = 0;

                    //设置socket参数
                    if (running && !paused && setSocketOptions(socket)) {
                        //处理该socket(关键)
                        if (!processSocket(socket)) {
                            countDownConnection();
                            //处理不了则关闭socket
                            closeSocket(socket);
                        }
                    } else {
                        countDownConnection();
                        closeSocket(socket);
                    }
                } catch (IOException x) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), x);
                    }
                } catch (NullPointerException npe) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), npe);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }


    protected boolean processSocket(Socket socket) {
        try {
            SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
            wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
            wrapper.setSecure(isSSLEnabled());
            // During shutdown, executor may be null - avoid NPE
            if (!running) {
                return false;
            }
            //包装成一个socket执行器然后丢入线程池中处理(服务器是一对多的,所以不能阻塞TCP接收线程,必须异步处理)
            getExecutor().execute(new SocketProcessor(wrapper));
        } catch (RejectedExecutionException x) {
            log.warn("Socket processing request was rejected for:"+socket,x);
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            log.error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    }

        在Acceptor的run方法中进行while循环,然后阻塞接受一个TCP的连接,设置一些参数后包装成一个SocketProcessor丢入线程池中异步执行(因为服务器是一对多的,不能阻塞当前的接收TCP连接)。

SocketProcessor:
            public void run() {
            boolean launch = false;
            synchronized (socket) {
                try {
                    SocketState state = SocketState.OPEN;

                    try {
                        //SSL的预处理
                        // SSL handshake
                        serverSocketFactory.handshake(socket.getSocket());
                    } catch (Throwable t) {
                        //省略
                    }

                    if ((state != SocketState.CLOSED)) {
                        if (status == null) {
                            //交给对应的协议处理器去处理,因为Tomcat还支持AJP协议
                            state = handler.process(socket, SocketStatus.OPEN_READ);
                        } else {
                            state = handler.process(socket,status);
                        }
                    }
                    //处理过程中状态被设置为关闭则直接关闭socket
                    if (state == SocketState.CLOSED) {
                        countDownConnection();
                        try {
                            socket.getSocket().close();
                        } catch (IOException e) {
                            // Ignore
                        }
                    }
                    //...省略
                } finally {
                    if (launch) {
                         //如果不能处理,则兜底关闭连接
                         handler.process(socket, SocketStatus.DISCONNECT);
                    }
            }
        }


Http11ConnectionHandler:
    public SocketState process(SocketWrapper<S> wrapper,
                SocketStatus status) {
            //拿到对应的socket(因为Tomcat支持NIO、JIO、APR三种运行模式,所以需要用泛型)
            S socket = wrapper.getSocket();
            if (socket == null) {
                // Nothing to do. Socket has been closed.
                return SocketState.CLOSED;
            }
            //拿到最终的协议处理器
            Processor<S> processor = connections.get(socket);
            if (status == SocketStatus.DISCONNECT && processor == null) {
                return SocketState.CLOSED;
            }
            //...省略

            try {
                //真正的处理SSL
                initSsl(wrapper, processor);

                SocketState state = SocketState.CLOSED;
                do {
                    if (status == SocketStatus.CLOSE_NOW) {
                        processor.errorDispatch();
                        state = SocketState.CLOSED;
                    //...省略
                    } else {
                        //此处根据状态最终调用处理
                        state = processor.process(wrapper);
                    }
                }
                //...省略
        }
    }


Http11Processor:
    public SocketState process(SocketWrapper<S> socketWrapper)
        throws IOException {
        //获取IO
        setSocketWrapper(socketWrapper);
        getInputBuffer().init(socketWrapper, endpoint);
        getOutputBuffer().init(socketWrapper, endpoint);

        //基本请求参数设值,keepAlive默认是true
        keepAlive = true;
        comet = false;
        openSocket = false;
        sendfileInProgress = false;
        readComplete = true;
        try {
                setRequestLineReadTimeout();
                //解析请求行 HTTP协议三部分(请求首行、请求头、请求体,其中请求体一般是用户自己使用时解析)
                if (!getInputBuffer().parseRequestLine(keptAlive)) {
                    if (handleIncompleteRequestLineRead()) {
                        break;
                    }
                }

                 //读取请求头(只是把请求头解析成Map形式,并没有根据里面的值做一些处理,也就是初步解析)
                 if (!getInputBuffer().parseHeaders()) {
                        openSocket = true;
                        readComplete = false;
                        break;
                 }    

            if (!getErrorState().isError()) {
                try {
                    //真正的解析请求头,解析请求头每个Key里面的value,常用的则校验数据格式等
                    prepareRequest();
                } catch (Throwable t) {
                    //...省略
                }
            }
            //如果没有错误,则继续处理
            if (!getErrorState().isError()) {
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    //调用适配器转交给最顶级容器(Engine)处理(关键)
                    adapter.service(request, response);
                    if(keepAlive && !getErrorState().isError() && (
                            response.getErrorException() != null ||
                                    (!isAsync() &&
                                    statusDropsConnection(response.getStatus())))) {
                        setErrorState(ErrorState.CLOSE_CLEAN, null);
                    }
                    setCometTimeouts(socketWrapper);
                } catch (InterruptedIOException e) {
                    setErrorState(ErrorState.CLOSE_NOW, e);
                } catch (HeadersTooLargeException e) {
                    if (response.isCommitted()) {
                        setErrorState(ErrorState.CLOSE_NOW, e);
                    } else {
                    }
                } catch (Throwable t) {
                    //...省略
                }
            }

            rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);

            if (!isAsync() && !comet) {
                if (getErrorState().isError()) {
                    getInputBuffer().setSwallowInput(false);
                } else {
                    checkExpectationAndResponseStatus();
                }
                //结束一个请求
                endRequest();
            }

            //设置状态和一些响应信息
            rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
            if (getErrorState().isError()) {
                response.setStatus(500);
            }
            request.updateCounters();

            if (!isAsync() && !comet || getErrorState().isError()) {
                if (getErrorState().isIoAllowed()) {
                    getInputBuffer().nextRequest();
                    getOutputBuffer().nextRequest();
                }
            }

            if (!disableUploadTimeout) {
                if(endpoint.getSoTimeout() > 0) {
                    setSocketTimeout(endpoint.getSoTimeout());
                } else {
                    setSocketTimeout(0);
                }
            }

            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

            if (breakKeepAliveLoop(socketWrapper)) {
                break;
            }
        }
        //...省略
    }

Adapter:
    public void service(org.apache.coyote.Request req,
                        org.apache.coyote.Response res)
        throws Exception {
//解析其它的HTTP参数,如?param=value(查询参数)、session和cookie处理、根据URL找到对应的Host和Contxt、Wrapper容器(因为要符合Servlet规范,很多参数都需要Tomcat为用户解析好)
boolean postParseSuccess = postParseRequest(req, request, res, response);
//真正转发给容器处理               
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

    }

        在SocketProcessor的run方法中,异步的进行解析,用对应的协议处理器处理,然后开始解析请求首行,请求头,等到解析完成并且没有错误时,则通过Adapter(适配器)的service方法,将请求传递给容器(Engine、Host、Context、Wrapper)。

        在组件介绍的文章中,我们知道Engine、Host、Context、Wrapper都属于容器Container,有共同的特性,如一样的生命周期、都有Pipeline(管道)、管道中都存在Valve(阀)。

        在Adapter的service方法中,获取的是Engine中Pipeline的第一个Valve去处理。

        Pipeline中有两种Valve,一种是普通Valve,一种是基础Valve。普通Valve也就是用户自定义添加使用的,而基础Vavle是用于当前容器兜底和传递给下一个容器使用的,所以在Adapter中传递下去的Request和Response最终要从上至下经过一个个的容器中的Vavle处理。

StandardEngineValve:
        public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        //从请求中获取对应的Host
        Host host = request.getHost();
        //调用Host的Valve
        host.getPipeline().getFirst().invoke(request, response);

    }



StandardHostValve:
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        Context context = request.getContext();

        if( context.getLoader() != null ) {
                //此处为当前线程设置应用的类加载器,从而实现应用之间class隔离(重点)
             Thread.currentThread().setContextClassLoader
                        (context.getLoader().getClassLoader());
        }
        //...省略
        //调用Context的Valve
        context.getPipeline().getFirst().invoke(request, response);
    }


StandardContextValve:

        public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        //确认请求
        response.sendAcknowledgement();
        //...省略
        //传递到最后一个Wrapper容器中处理
        wrapper.getPipeline().getFirst().invoke(request, response);
    }


StandardWrapperValve:
        public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        boolean unavailable = false;
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();
        if (!unavailable) {
            //通过Wrapper容器获取或创建一个Servlet
           servlet = wrapper.allocate();
        }
        //...省略
        //根据请求信息创建一条过滤器链
        ApplicationFilterFactory factory =
            ApplicationFilterFactory.getInstance();
        ApplicationFilterChain filterChain =
            factory.createFilterChain(request, wrapper, servlet);

        try {
             //调用过滤器链处理请求,这就是我们经常配置的Filter过滤器
             filterChain.doFilter(request.getRequest(), response.getResponse());
        } catch (Throwable e) {
            //异常处理
            exception(request, response, e);
        }

    }

StandardWrapper:
        public Servlet allocate() throws ServletException {

        if (!singleThreadModel) {
            //此处可以看到使用的是双重校验加锁的单例模式,所以Wrapper容器其实就是Servlet的包装,一个Wrapper容器对应一个单例的Servlet
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        //通过反射创建自定义的Servlet对象
                        instance = loadServlet();
                        if (!singleThreadModel) {
                            newInstance = true;
                            countAllocated.incrementAndGet();
                        }
                    }
                }
            }
            //如果没有初始化则初始化
            if (!instanceInitialized) {
                initServlet(instance);
            }

    }

    private synchronized void initServlet(Servlet servlet)
            throws ServletException {
        //初始化调用Servlet的init方法
        servlet.init(facade);
    }


ApplicationFilterChain:
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {

        internalDoFilter(request,response);
    }

    private void internalDoFilter(ServletRequest request, 
                                  ServletResponse response)
        throws IOException, ServletException {
            ApplicationFilterConfig filterConfig = filters[pos++];
            Filter filter = null;
         try {
            filter = filterConfig.getFilter();
            //调用过滤器执行
            filter.doFilter(request, response, this);
        } catch (Throwable e) {
                //省略...异常处理
        }
        if ((request instanceof HttpServletRequest) &&
            (response instanceof HttpServletResponse)) {
                //最终调用到用户自定义的Servlet的service方法中
                servlet.service(request, response);
        }

    }    

         Engine把Request通过PipeLine中的Valve传递到最终的Wrapper中,用户可以在这几个容器(Engine、Host、Context、Wrapper)的PipeLine添加普通的Valve进行一些操作。

        终于,在Wrapper中,Tomcat通过单例模式创建出用户自定义的Servlet,然后经过过滤器链的处理后,调用到Servlet的service方法中,此方法也是给用户实现处理请求的最终方法。

        时序图:

                

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值