Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tomcat Pipeline Value机制 #6

Open
luoxn28 opened this issue May 12, 2018 · 0 comments
Open

Tomcat Pipeline Value机制 #6

luoxn28 opened this issue May 12, 2018 · 0 comments

Comments

@luoxn28
Copy link
Contributor

luoxn28 commented May 12, 2018

Pipeline Value机制是Tomcat请求处理过程中的一种处理模式,可以理解成是管道+阀门的处理模式,这里Pipeline就是管道,Value就是Pipeline中的几个阀门,请求会经过每个管道中的每个Value依次处理,Pipeline Value相互配合,共同完成请求处理。

每个容器(Engine/Host/Context/Wrap)包含一个pipeline,每个pipeline包含一个valve集合,位于前面的valve做完业务处理后将调用后面的valve做业务处理,而容器的缺省valve位于集合的最后一个位置,负责调用下层容器的pipeline的第一个valve做请求处理。调用会从Engine的第一个valve调用开始,一直执行到调用Wrapper的缺省valve:StandardWrapperValve,而filter与servlet的处理就是在这个valve中进行的 。Engine的第一个valve是由Adapter调用的,在connector章节中也看到CoyoteAdapter在处理完request以后会执行connector.getContainer().getPipeline().getFirst().invoke(request, response)

image
Pipeline接口方法如上,该接口有一个实现类StandardPipeline。Pipeline中有一个Value链,这些Value具有不同的功能,比如访问日志记录等。Pipeling中至少有一个默认Value,并且默认Value是作为Value链上的最后一个,负责调用下一个Pipeline的Value逻辑。Value接口定义如下:
image

1 默认Value

Engine缺省的valve StandardEngineValve

public final void invoke(Request request, Response response)
    throws IOException, ServletException {
    // Select the Host to be used for this Request
    Host host = request.getHost();
    if (host == null) {
        // ...
        return;
    }
 
    // Ask this Host to process this request
    host.getPipeline().getFirst().invoke(request, response);
}

Host的缺省valve StandardHostValve

public final void invoke(Request request, Response response)  
    throws IOException, ServletException {  
    // 定位context  
    Context context = request.getContext();  
    if (context == null) {  
        // ......  
        return;  
    }  
    // ......  
 
    // 调用context的第一个valve  
    context.getPipeline().getFirst().invoke(request, response); 
    // ...
}

context的缺省valve StandardContextValve

public final void invoke(Request request, Response response)
        throws IOException, ServletException {
    // Select the Wrapper to be used for this Request
    Wrapper wrapper = request.getWrapper();
    if (wrapper == null || wrapper.isUnavailable()) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    // ...
    wrapper.getPipeline().getFirst().invoke(request, response);
}

wrapper的缺省value StandardWrapperValue

public final void invoke(Request request, Response response)
        throws IOException, ServletException {
         
    requestCount.incrementAndGet();
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();
 
    // Allocate a servlet instance to process this request
    try {
        if (!unavailable) {
            //加载servlet  
            servlet = wrapper.allocate();
        }
    } catch (UnavailableException e) {
        // ...
    }
 
    // Create the filter chain for this request
    // 根据配置建立一个filter-servlet的处理链表,servlet在链表的尾端
    ApplicationFilterChain filterChain =
            ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
 
    // Call the filter chain for this request
    // NOTE: This also calls the servlet's service() method
    // filter调用链执行
    filterChain.doFilter
        (request.getRequest(), response.getResponse());
    // ...
}

2 Engine/Host/Context/Wrap容器

image

StandardEngine、StandardHost、StandardContext、StandardWrapper都继承自ContainerBase,ContainerBase有一个属性:

/**
 * The Pipeline object with which this Container is associated.
 */
protected final Pipeline pipeline = new StandardPipeline(this);

在StandardEngine、StandardHost、StandardContext、StandardWrapper各自的构造方法中,都有调用pipeline.setBasic()来设置pipeline的默认Value,注意默认Value是该pipeline的最后一个Value。

有了设置了pipeline的Engine/Host/Context/Wrap容器,在CoyoteAdapter.service方法中,就可以从Engine开始获取pipeline的Value开始对(request, response)处理了:

// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

参考资料:
1、tomcat:pipeline与valve机制

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant