博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
吸猫就吸Tomcat之Pipeline-Valve巧妙设计
阅读量:6590 次
发布时间:2019-06-24

本文共 2281 字,大约阅读时间需要 7 分钟。

前言

于每一个Java工程师而言,tomcat这只小橘猫算是我们的老朋友了,同时tomcat作为一款服务器中间件具备了很强的扩展性,内部对于Request和Response的逻辑处理都是何种方式来实现的呢?本文将主要介绍tomcat的Pipeline-Valve设计来一窥究竟。

接口介绍

首先我们看看Valve接口

可以从Valve看到很多链表的影子,我们可以根据Valve来构造一条Valve链。接下来看看Pipeline接口

Pipeline接口的主要方法

可以看到Pipeline的主要方法提供了对Valve的增删查改操作,其中有两个关键的方法setBasic(Valve)与addValve(Valve)我们跟进源码看一看。其中StandardPipeline是Pipeline接口的实现类,下面我截取了setBasic最核心的逻辑,可以看出basic实际上就是Pipeline维护的Valve链里最末尾的一个Valve

Valve current = first;while (current != null) {if (current.getNext() == oldBasic) {current.setNext(valve);break;}current = current.getNext();}this.basic = valve;复制代码

同样的我们来看一看addValve的源码,以下是最核心的部分

Valve current = first;while (current != null) {if (current.getNext() == basic) {current.setNext(valve);valve.setNext(basic);break;}复制代码

通过addValve添加的Valve被加在了basic的前一个,也就是说basic永远指向Valve链里的最后一个Valve,不会被轻易替代,那么这种设计有什么意义呢?待会给出答案~

Valve到底是什么?

上图都是Valve接口的实现类,包含了负载均衡、单点登录等tomcat容器本身的逻辑。通过查看Valve接口invoke方法的实现可以知道,每一个Valve的invoke方法主要做两件事情

  1. 本身的逻辑
  2. 通过getNext().invoke(request, response)调用下一个Valve的逻辑

这是很经典的责任链设计模式。简单的说一个valve就是一个逻辑体。

跟踪basic

可以看到setBasic的使用方主要是tomcat内置的四大容器,Context、Engine、Host以及Wrapper,先简单对四大容器做个介绍

  • Wrapper:对Servlet定义的组件概念,一个Wrapper代表一个Servlet
  • Context:表示我们的应用程序,比如一个运行中Java Web程序,一个程序里面自然有多个Servlet,所以Conxtet和Wrapper的关系是1对n
  • Host:表示虚拟主机的概念,因为一台服务器不仅能够对product.yangkw.com提供服务,同时也可以对test.yangkw.com提供服务,同时每个虚拟主机都可以运行多个Java Web程序,所以Host和Context的关系也是1对n
  • Engine:Tomcat连接器(Connector) 将接收到的连接提交给Engine处理,作为整个Servlet引擎的组件概念,用来管理多个虚拟站点,Engine和Host也是一对n的关系

下面是关于四大容器一个简单的类图关系

那么四大容器是如何被关联在一起的呢?StandardEngineValve是Engine容器的basic valve,笔者简化了代码实现,保留最主要的逻辑

@Overridepublic final void invoke(Request request, Response response)throws IOException, ServletException {// Select the Host to be used for this RequestHost host = request.getHost();...// Ask this Host to process this requesthost.getPipeline().getFirst().invoke(request, response);}复制代码

可以看到Engine容器的basic valve负责触发host容器pipeline 答案出来了:每个容器的basic valve会去触发子容器的pipeline,所以basic作为一个valve不仅要执行自身相应的逻辑,同时也扮演了一个外交官的角色负责去和其子容器逻辑的对接。

总结

  • pipeline可以看做是valve的容器
  • 四大容器里每个容器都维护有自身专属的pipeline
  • basic负责触发子容器的第一个valve
  • wrapper的basic会去调用filter,然后再执行servlet的逻辑
  • FilterChain和Pipeline-Valve很相似,区别是filterChain是业务层面里的而Pipeline-Valve是tomcat自身层面的。

参考资料

  • 《Tomcat 架构解析》
  • 极客时间《深入拆解Tomcat&Jetty》

转载于:https://juejin.im/post/5ceb42f5e51d45775a700286

你可能感兴趣的文章
【3分钟就会系列】使用Ocelot+Consul搭建微服务吧!
查看>>
新年新气象[xgluxv]
查看>>
电影图标:杀死比尔(Kil Bill)
查看>>
(原創) Object是由Property、Method、Event构成的吗? (C/C++) (OO) (Database) (Visual FoxPro)
查看>>
Mybatis3.3——源码阅读笔记
查看>>
oracle中的trunc函数操作
查看>>
杂牌蓝牙在2003系统使用新驱动的破解方法!
查看>>
EventCache表太大, 怎么办?
查看>>
Top 10 mistakes in Eclipse Plug-in Development
查看>>
Directx教程(23) 简单的光照模型(2)
查看>>
判断站点访问的终端类型(移动端还是pc端)的方法
查看>>
使用sphinx来创建文档
查看>>
001淘淘商城项目:项目的Maven工程搭建
查看>>
[转]用了docker是否还有必要使用openstack?
查看>>
浅谈游戏的声音处理-流播放文件 source
查看>>
c语言之cgi实例
查看>>
Direct2D教程(八)梯度色画刷
查看>>
Swift vs. Objective-C:未来看好 Swift 的十个理由
查看>>
Java 并发性和多线程
查看>>
IE6下frameset横向滚动条BUG
查看>>