(四)Tomcat架构及运行原理之请求处理

目录

1. 请求的处理及Container通信

1.1 Processor

1.1.1 AbstractProcessorLight

1.1.2 AbstractProcessor

1.1.3 Http11Processor

1.2 Adapter

1.3 StandardPipeline

1.4 StandardEngineValve

1.5 StandardHostValve

1.6 StandardContextValve

1.7 StandardWrapperValve

1.8 ApplicationFilterChain

在阅读本篇笔记前请先看(三)Tomcat架构及运行原理之Connector源码分析文章。

1. 请求的处理及Container通信

1.1 Processor

在上篇笔记中,我们已经介绍过了Connector中是如何从Container调用到Connector中,而Connector又是如何创建Socket监听机制以及和本篇需要讲的对具体请求进行处理入口。本篇着重于从handler到Servlet整个流程的通信。先看到关键的processor接口源码:

public interface Processor {
    SocketState process(SocketWrapperBase<?> socketWrapper, 
            SocketEvent status) throws IOException;
    UpgradeToken getUpgradeToken();
    boolean isUpgrade();
    boolean isAsync();
    void timeoutAsync(long now);
    Request getRequest();
    void recycle();
    void setSslSupport(SSLSupport sslSupport);
    ByteBuffer getLeftoverInput();
    void pause();
    boolean checkAsyncTimeoutGeneration();
}

本接口process接口无疑是最重要的,但是getRequest方法和recycle方法也是需要注意的。

1.1.1 AbstractProcessorLight

首先看到Processor接口的实现子类AbstractProcessorLight。其部分关键源码如下:

public abstract class AbstractProcessorLight implements Processor {
    @Override
    public SocketState process(SocketWrapperBase<?> socketWrapper, 
            SocketEvent status)
            throws IOException {
        // 设置为CLOSED是为了等下不用再设置状态而可以直接跳出do-while循环
        SocketState state = SocketState.CLOSED;
        Iterator<DispatchType> dispatches = null;
        do {
            // 中间的调用dispatch可以忽略,因为和HTTP请求无关
            // Websocket才会用到
            if (dispatches != null) {
                ...
            } else if (status == SocketEvent.OPEN_READ){
                // 执行HTTP请求方法,具体实现交给子类实现
                state = service(socketWrapper);
            } else {
                state = SocketState.CLOSED;
            }
            // 异步执行
            if (state != SocketState.CLOSED && isAsync()) {
                state = asyncPostProcess();
            }
            if (dispatches == null || !dispatches.hasNext()) {
                dispatches = getIteratorAndClearDispatches();
            }
        } while (state == SocketState.ASYNC_END ||
                dispatches != null && state != SocketState.CLOSED);
        return state;
    }
    protected abstract SocketState service(
            SocketWrapperBase<?> socketWrapper) throws IOException;
    protected abstract SocketState dispatch(SocketEvent status) 
            throws IOException;
}

本类也只是一个模板方法,在父类中确定根据哪些状态去执行哪些方法。普通的HTTP请求和service相关,而诸如Websocket和dispatch相关。

1.1.2 AbstractProcessor

这个类起到承上启下的作用。其部分关键源码如下:

public abstract class AbstractProcessor extends AbstractProcessorLight 
        implements ActionHook {
    protected final Adapter adapter;
    protected final Request request;
    protected final Response response;
    protected volatile SocketWrapperBase<?> socketWrapper = null;
    protected volatile SSLSupport sslSupport;
    public AbstractProcessor(Adapter adapter) {
        this(adapter, new Request(), new Response());
    }
    protected AbstractProcessor(Adapter adapter, Request coyoteRequest, 
            Response coyoteResponse) {
        this.adapter = adapter;
        asyncStateMachine = new AsyncStateMachine(this);
        request = coyoteRequest;
        response = coyoteResponse;
        response.setHook(this);
        request.setResponse(response);
        request.setHook(this);
        userDataHelper = new UserDataHelper(getLog());
    }
}

可以看到,这个类关键的代码很少(指的是在启动Tomcat时和普通的HTTP请求进来时,关键部分只是这一部分代码)。其关键则是设置Adapter、request和response对象,需要注意的是此时的request和response是org.apache.coyote包下的,和我们平时见到的不是同一个。

1.1.3 Http11Processor

其部分关键源码如下:

public class Http11Processor extends AbstractProcessor {
    private final AbstractHttp11Protocol<?> protocol;
    private final Http11InputBuffer inputBuffer;
    private final Http11OutputBuffer outputBuffer;
    private final HttpParser httpParser;
    public Http11Processor(AbstractHttp11Protocol<?> protocol, 
            Adapter adapter) {
        super(adapter);
        this.protocol = protocol;
        httpParser = new HttpParser(protocol.getRelaxedPathChars(),
                protocol.getRelaxedQueryChars());
        inputBuffer = new Http11InputBuffer(request, 
                protocol.getMaxHttpHeaderSize(),
                protocol.getRejectIllegalHeaderName(), httpParser);
        request.setInputBuffer(inputBuffer);
        outputBuffer = new Http11OutputBuffer(response, 
                protocol.getMaxHttpHeaderSize());
        response.setOutputBuffer(outputBuffer);
        inputBuffer.addFilter(new IdentityInputFilter(
                protocol.getMaxSwallowSize()));
        outputBuffer.addFilter(new IdentityOutputFilter());
        inputBuffer.addFilter(new ChunkedInputFilter(protocol
                .getMaxTrailerSize(),
                protocol.getAllowedTrailerHeadersInternal(), 
                protocol.getMaxExtensionSize(),
                protocol.getMaxSwallowSize()));
        outputBuffer.addFilter(new ChunkedOutputFilter());
        inputBuffer.addFilter(new VoidInputFilter());
        outputBuffer.addFilter(new VoidOutputFilter());
        inputBuffer.addFilter(new BufferedInputFilter());
        outputBuffer.addFilter(new GzipOutputFilter());
        pluggableFilterIndex = inputBuffer.getFilters().length;
    }
    @Override
    public SocketState service(SocketWrapperBase<?> socketWrapper)
        throws IOException {
        // 先对参数进行初始化,略过
        ...
        while (!getErrorState().isError() && keepAlive && !isAsync() && 
                upgradeToken == null &&
                sendfileState == SendfileState.DONE && 
                !protocol.isPaused()) {
            // 中间验证request、设置request和判断Upgrade的流程便略过
            ...
            if (getErrorState().isIoAllowed()) {
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    // 获得Adapter去调用service
                    // 这里的Adapter实则是CoyoteAdapter类型
                    getAdapter().service(request, response);
                    if(keepAlive && !getErrorState().isError() && 
                            !isAsync() &&
                            statusDropsConnection(response.getStatus())) {
                        setErrorState(ErrorState.CLOSE_CLEAN, null);
                    }
                } catch (InterruptedIOException e) {
                    ...
                } 
            }
            // 状态的判断略过
            ...
            sendfileState = processSendfile(socketWrapper);
        }
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
        // 状态返回略过
        ...
    }
    @Override
    public final void recycle() {
        getAdapter().checkRecycled(request, response);
        super.recycle();
        inputBuffer.recycle();
        outputBuffer.recycle();
        upgradeToken = null;
        socketWrapper = null;
        sendfileData = null;
        sslSupport = null;
    }
}

 该类中一共只有三个方法需要留意:构造函数,service方法和recycle。构造函数确定了类中对象的具体类型,而recycle方法则是将类中的各个属性设置为最开始的状态。service方法在代码中进行了说明,其它流程都是对状态和结果的判断,最重要的便是调用adapter的service方法。

1.2 Adapter

终于到了Adapter来了,这个类的作用便是将Connector组件的类调用到Container类中,当然Container中的组件通信都是使用管道来通信的,因此Adapter实际上对接的是Connector和Pipeline。

其部分关键源码如下:

public class CoyoteAdapter implements Adapter {
    private final Connector connector;
    public CoyoteAdapter(Connector connector) {
        super();
        this.connector = connector;
    }
    @Override
    public void service(org.apache.coyote.Request req, 
            org.apache.coyote.Response res)
            throws Exception {
        // 将org.apache.coyote包下的request和response转换成
        // org.apache.catalina.connector包下继承HttpServletRequest类型
        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);
        if (request == null) {
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);
            request.setResponse(response);
            response.setRequest(request);
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);
            req.getParameters().setQueryStringCharset(
                    connector.getURICharset());
        }
        // 中间略过
        ...
        try {
            // 解析并设置Catalina核心属性和特定请求配置,如host、context、
            // 参数、请求方式、允许的请求方式和版本等信息
            // 当然,非常重要的信息就是根据请求路径来判断由哪个
            // StandardWrapper处理这个请求也是在这里面完成的
            postParseSuccess = 
                    postParseRequest(req, request, res, response);
            if (postParseSuccess) {
                // 检查是否支持异步止回阀
                request.setAsyncSupported(
                        connector.getService().getContainer()
                        .getPipeline().isAsyncSupported());
                // 调用进Container中,这里是关键,由Connector部分调用进了
                // Container,完成两者的适配
                connector.getService().getContainer().getPipeline()
                        .getFirst().invoke(request, response);
            }
            ...
        } catch (IOException e) {
            ...
        } finally {
            ...
        }
    }
}

可以看到,Adapter从名字便可以看出来这是个适配器,从其关键源码的实现可以看出来其适配了Connector和Container,使Connector能够成功的调用进Container。在这里面也完成了request和response的类型转换,将Connector组件中的转换成了Container中的。

1.3 StandardPipeline

各个容器都是使用StandardPipeline管道类来进行连通的,同时管道中又保存了Valve阈的关联关系,可以看到其关键部分源码:

public class StandardPipeline extends LifecycleBase implements Pipeline {
    protected Container container = null;
    protected Valve basic = null;
    protected Valve first = null;
    @Override
    public Valve getFirst() {
        if (first != null) {
            return first;
        }
        return basic;
    }
}

从其关键源码中便可以得知这个类只是一个中介类(主要负责连接的管道当然只负责连接对方,而不需要进行逻辑操作),保存了Container和处理管道对应的valve阈。

1.4 StandardEngineValve

Container的运行架构图便不再这里赘述,看过前面总体架构分析便能得知。其关键源码如下:

final class StandardEngineValve extends ValveBase {
    protected Container container = null;
    protected Valve next = null;
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        Host host = request.getHost();
        if (host == null) {
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(host.getPipeline()
                    .isAsyncSupported());
        }
        host.getPipeline().getFirst().invoke(request, response);
    }
}

该类实际上只对host进行了某些判断,并直接获得host调用其管道进行下个容器的流程。

1.5 StandardHostValve

其关键源码如下:

final class StandardHostValve extends ValveBase {
    protected Container container = null;
    protected Valve next = null;
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        Context context = request.getContext();
        if (context == null) {
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(context.getPipeline()
                    .isAsyncSupported());
        }
        boolean asyncAtStart = request.isAsync();
        try {
            context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
            if (!asyncAtStart && 
                    !context.fireRequestInitEvent(request.getRequest())) {
                return;
            }
            try {
                if (!response.isErrorReportRequired()) {
                    // 继续执行管道连接的下个Container方法
                    context.getPipeline().getFirst()
                            .invoke(request, response);
                }
            } catch (Throwable t) {
                ...
            }
            // 后置处理
            ...
        } finally {
            if (ACCESS_SESSION) {
                request.getSession(false);
            }
            context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
        }
    }
}

该阈和上一个差不了多少,也只是对request和response进行一些状态处理。

1.6 StandardContextValve

其关键源码如下:

final class StandardContextValve extends ValveBase {
    protected Container container = null;
    protected Valve next = null;
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        // 如果不允许直接访问WEB-INF或META-INF下的资源
        MessageBytes requestPathMB = request.getRequestPathMB();
        if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/META-INF"))
                || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
                || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        Wrapper wrapper = request.getWrapper();
        if (wrapper == null || wrapper.isUnavailable()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        try {
            // 确认请求
            response.sendAcknowledgement();
        } catch (IOException ioe) {
            ...
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(wrapper.getPipeline()
                    .isAsyncSupported());
        }
        wrapper.getPipeline().getFirst().invoke(request, response);
    }
}

执行一些判断是否有权限访问WEB-INF或者META-INF文件夹下的资源,确认请求等操作。接着往下调用Wrapper对应管道的阈。

1.7 StandardWrapperValve

其关键源码如下:

final class StandardWrapperValve extends ValveBase {
    protected Container container = null;
    protected Valve next = null;
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {
        // 初始化本地方法可能会用到的参数
        boolean unavailable = false;
        Throwable throwable = null;
        requestCount.incrementAndGet();
        StandardWrapper wrapper = (StandardWrapper) getContainer();
        Servlet servlet = null;
        Context context = (Context) wrapper.getParent();
        // 检查标记为不可用的应用程序
        if (!context.getState().isAvailable()) {
            ...
        }
        // servlet被标记为不可用
        if (!unavailable && wrapper.isUnavailable()) {
            ...
        }
        // 分配一个servlet实例来处理请求
        try {
            if (!unavailable) {
                // allocate实际上会调用StandardWrapper的initServlet方法
                // 去实例化一个Servlet,并调用Servlet的init方法。
                servlet = wrapper.allocate();
            }
        } catch (Throwable e) {
            ...
        }
        ...
        // 为此请求创建过滤器链
        ApplicationFilterChain filterChain = ApplicationFilterFactory
                .createFilterChain(request, wrapper, servlet);
        // 为此请求调用过滤器链
        Container container = this.container;
        try {
            if ((servlet != null) && (filterChain != null)) {
                if (context.getSwallowOutput()) {
                    try {
                        SystemLogHandler.startCapture();
                        if (request.isAsyncDispatching()) {
                            request.getAsyncContextInternal()
                                    .doInternalDispatch();
                        } else {
                            filterChain.doFilter(request.getRequest(),
                                    response.getResponse());
                        }
                    } finally {
                        String log = SystemLogHandler.stopCapture();
                        if (log != null && log.length() > 0) {
                            context.getLogger().info(log);
                        }
                    }
                } else {
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal()
                                .doInternalDispatch();
                    } else {
                        filterChain.doFilter
                            (request.getRequest(), response.getResponse());
                    }
                }
            }
        } catch (Throwable e) {
            ...
        } finally {
            ...
        }
    }
}

可以看到这个阈中除了对request的请求进行校验外,还在其中初始化了StaddardWrapper封装的Servlet,并且从request中获得过滤器链并初始化,最后调用过滤器链。

1.8 ApplicationFilterChain

Servlet的过滤器链实在太多,因此我们只挑其中统筹兼顾的一个来进行分析。其关键源码如下:

public final class ApplicationFilterChain implements FilterChain {
    private static final ThreadLocal<ServletRequest> lastServicedRequest;
    private static final ThreadLocal<ServletResponse> lastServicedResponse;
    private Servlet servlet = null;
    // 当前读取的过滤器位置
    private int pos = 0;
    // 过滤器数量
    private int n = 0;
    @Override
    public void doFilter(ServletRequest request, ServletResponse response)
        throws IOException, ServletException {
        if( Globals.IS_SECURITY_ENABLED ) {
            // 可以忽略
            ...
        } else {
            internalDoFilter(request,response);
        }
    }
    private void internalDoFilter(ServletRequest request,
            ServletResponse response)
            throws IOException, ServletException {
        // 
        if (pos < n) {
            // 获得过滤器链中的过滤器
            ApplicationFilterConfig filterConfig = filters[pos++];
            try {
                Filter filter = filterConfig.getFilter();
                // 忽略
                ...
                if( Globals.IS_SECURITY_ENABLED ) {
                    // 忽略
                    ...
                } else {
                    // 调用过滤器链中的过滤器
                    filter.doFilter(request, response, this);
                }
            }  catch (Throwable e) {
                ...
            }
            return;
        }
    
        // 到这里代表前面的过滤器已经全部执行完毕,是时候该执行Servlet了
        try {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(request);
                lastServicedResponse.set(response);
            }
            if (request.isAsyncSupported() && !servletSupportsAsync) {
                request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                        Boolean.FALSE);
            }
            // Use potentially wrapped request from this point
            if ((request instanceof HttpServletRequest) &&
                    (response instanceof HttpServletResponse) &&
                    Globals.IS_SECURITY_ENABLED ) {
                // 忽略
                ...
            } else {
                // 执行Servlet的service方法
                servlet.service(request, response);
            }
        }  catch (Throwable e) {
            ...
        } finally {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest.set(null);
                lastServicedResponse.set(null);
            }
        }
    }
}

 暂且把这个调用其它过滤器的类交模板过滤器,在这个过滤器关键方法中可以分成两部分,一部分是前面的调用各个过滤器逻辑,一个则是后续调用Servlet的逻辑。调用到过滤器和servlet后便无需多言了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值