tomcat源码分析-pipeline管道机制

本文深入探讨了Tomcat的Pipeline和Valve机制。Pipeline作为容器间的通信桥梁,每个容器拥有自己的Pipeline,其中包含至少一个基础Valve。Valve是处理请求的组件,它们形成一个链式结构,每个Valve可以执行特定操作。Pipeline通过next指针链接Valve,请求从Engine开始,逐级通过Host、Context到Wrapper进行处理。StandardPipeline是Pipeline的实现,包含了添加、移除和管理Valve的方法。通过对Valve接口和Pipeline的了解,我们可以更好地理解Tomcat的内部工作流程。

本文主要目的是讲解tomcat中的pipeline机制
我们前面文章介绍过,tomcat中container有四种,分别是engine,host,context,wrapper,这4个。
container的实现类分别是StandardEngine,StandardHost,StandardContext,StandardWrapper。四个容器是包含关系,engine包含host,host包含context,context,包含wrapper,wappper代表最基础的一个servlet。
在这里插入图片描述
tomcat由Connector和Container两部分组成,而当网络请求过来的时候Connector先将请求包装为Request,然后将Request交由Container进行处理,最终返回给请求方。而Container处理的第一层就是Engine容器,但是在tomcat中Engine容器不会直接调用Host容器去处理请求,那么请求是怎么在4个容器中流转的,4个容器之间是怎么依次调用的,我们今天来讲解下。
当请求到达Engine容器的时候,Engine并非是直接调用对应的Host去处理相关的请求,而是调用了自己的一个组件去处理,这个组件就叫做pipeline组件,跟pipeline相关的还有个也是容器内部的组件,叫做valve组件。

在Catalina中,我们有4种容器,每个容器都有自己的Pipeline组件,每个Pipeline组件上至少会设定一个Valve(阀门),这个Valve我们称之为BaseValve(基础阀)。基础阀的作用是连接当前容器的下一个容器(通常是自己的自容器),可以说基础阀是两个容器之间的桥梁。

Pipeline定义对应的接口Pipeline,标准实现了StandardPipeline。Valve定义对应的接口Valve,抽象实现类ValveBase,4个容器对应基础阀门分别是StandardEngineValve,StandardHostValve,StandardContextValve,StandardWrapperValve。

catalina中pipeline,valve运行图如下
在这里插入图片描述
一个pipline上由多个valve,每个valve都可以做一些操作,无论是pipeline还是valve操作,都是request和response。再容器之间pipeline和valve则起到了桥梁的作用。

我们看下valve的接口

public interface Valve {
    public String getInfo();
    public Valve getNext();
    public void setNext(Valve valve);
    public void backgroundProcess();
    public void invoke(Request request, Response response) throws IOException, ServletException;
    public void event(Request request, Response response, CometEvent event) throws IOException,ServletException;
    public boolean isAsyncSupported();
}

先看下valve接口的方法定义,方法不是很多,这里只介绍setNext(),getNext。在上面我们也看到了一个pipeline上面有很多valve。这些valve存放并非统一放在pipiline中,而是像链表,通过next指针相连。

pipeline

//pipeline 接口
public interface Pipeline {
    public Valve getBasic();
    public void setBasic(Valve valve);
    public void addValve(Valve valve);
    public Valve[] getValves();
    public void removeValve(Valve valve);
    public Valve getFirst();
    public boolean isAsyncSupported();
    public Container getContainer();
    public void setContainer(Container container);
}

可以看出Pipeline中很多的方法都是操作Valve的,包括获取,设置,移除Valve,getFirst()返回的是Pipeline上的第一个Valve,而getBasic(),setBasic()则是获取/设置基础阀,我们都知道在Pipeline中,每个pipeline至少都有一个阀门,叫做基础阀,而getBasic(),setBasic()则是操作基础阀的。

  • standardPipeline
public class StandardPipeline extends LifecycleBase implements Pipeline, Contained {
private static final Log log = LogFactory.getLog(StandardPipeline.class);
public StandardPipeline() {
    this(null);
}
public StandardPipeline(Container container) {
    super();
    setContainer(container);
}
protected Valve basic = null;
protected Container container = null;
protected static final String info = "org.apache.catalina.core.StandardPipeline/1.0";
//当前pipline的第一个阀门
protected Valve first = null;
//这里是生命周期的初始化方法
@Override
protected synchronized void startInternal() throws LifecycleException {

    // Start the Valves in our pipeline (including the basic), if any
    Valve current = first;
    if (current == null) {
        current = basic;
    }
    while (current != null) {
        if (current instanceof Lifecycle)
            ((Lifecycle) current).start();
        current = current.getNext();
    }

    setState(LifecycleState.STARTING);
}

// ------------------------------------------------------- Pipeline Methods
//设置基础阀
@Override
public void setBasic(Valve valve) {

    // Change components if necessary
    Valve oldBasic = this.basic;
    if (oldBasic == valve)
        return;

    // Stop the old component if necessary
    //先停掉oldBasic,生命周期关掉
    if (oldBasic != null) {
        if (getState().isAvailable() && (oldBasic instanceof Lifecycle)) {
            try {
                ((Lifecycle) oldBasic).stop();
            } catch (LifecycleException e) {
                log.error("StandardPipeline.setBasic: stop", e);
            }
        }
        if (oldBasic instanceof Contained) {
            try {
                ((Contained) oldBasic).setContainer(null);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
            }
        }
    }

    //启动新的阈值
    if (valve == null)
        return;
    if (valve instanceof Contained) {
        ((Contained) valve).setContainer(this.container);
    }
    if (getState().isAvailable() && valve instanceof Lifecycle) {
        try {
            ((Lifecycle) valve).start();
        } catch (LifecycleException e) {
            log.error("StandardPipeline.setBasic: start", e);
            return;
        }
    }

    // Update the pipeline
    Valve current = first;
    while (current != null) {
    //遍历阀门链表将新的阀门取代旧的阀门
    //base节点添加到链表的最后,替换旧的阈值
        if (current.getNext() == oldBasic) {
            current.setNext(valve);
            break;
        }
        current = current.getNext();
    }
    
    this.basic = valve;

}

//添加阈值
@Override
public void addValve(Valve valve) {

    // Validate that we can add this Valve
    if (valve instanceof Contained)
        ((Contained) valve).setContainer(this.container);

    // Start the new component if necessary
    if (getState().isAvailable()) {
        if (valve instanceof Lifecycle) {
            try {
                ((Lifecycle) valve).start();
            } catch (LifecycleException e) {
                log.error("StandardPipeline.addValve: start: ", e);
            }
        }
    }

    // Add this Valve to the set associated with this Pipeline
    if (first == null) {
        first = valve;
        valve.setNext(basic);
    } else {
    //添加到basic节点的前一个位置
        Valve current = first;
        while (current != null) {
            if (current.getNext() == basic) {
                current.setNext(valve);
                valve.setNext(basic);
                break;
            }
            current = current.getNext();
        }
    }
    
    container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
}

//获取阀门
@Override
public Valve[] getValves() {
    ArrayList<Valve> valveList = new ArrayList<Valve>();
    Valve current = first;
    if (current == null) {
        current = basic;
    }
    while (current != null) {
        valveList.add(current);
        current = current.getNext();
    }

    return valveList.toArray(new Valve[0]);

}


//删除阀门,
@Override
public void removeValve(Valve valve) {

    Valve current;
    //删除的是第一个阀门,直接置空第一个节点
    if(first == valve) {
        first = first.getNext();
        current = null;
    } else {
        current = first;
    }
    //遍历节点,删除节点的上一个节点,指向删除节点下一个节点
    while (current != null) {
        if (current.getNext() == valve) {
            current.setNext(valve.getNext());
            break;
        }
        current = current.getNext();
    }
	//检查,如果第一个节点是基节点,置空
    if (first == basic) first = null;

    if (valve instanceof Contained)
        ((Contained) valve).setContainer(null);

    if (valve instanceof Lifecycle) {
        // Stop this valve if necessary
        if (getState().isAvailable()) {
            try {
                ((Lifecycle) valve).stop();
            } catch (LifecycleException e) {
                log.error("StandardPipeline.removeValve: stop: ", e);
            }
        }
        try {
            ((Lifecycle) valve).destroy();
        } catch (LifecycleException e) {
            log.error("StandardPipeline.removeValve: destroy: ", e);
        }
    }
   container.fireContainerEvent(Container.REMOVE_VALVE_EVENT, valve);
}
	//如果第一个节点不空位,返回基节点
    @Override
    public Valve getFirst() {
        if (first != null) {
            return first;
        }
        
        return basic;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值