【总结】Tomcat原理剖析

来源:互联网 发布:淘宝助理5.5下载mac 编辑:程序博客网 时间:2024/06/05 05:57
  • Tomcat模块
    • Service
      • 我们将 Tomcat 中 Connector、Container 作为一个整体比作一对情侣的话,Connector 主要负责对外交流,可以比作为 Boy,Container 主要处理 Connector 接受的请求,主要是处理内部事务,可以比作为 Girl。那么这个 Service 就是连接这对男女的结婚证了。是 Service 将它们连接在一起,共同组成一个家庭
      • Service 只是在 Connector 和 Container 外面多包一层,把它们组装在一起,向外面提供服务,一个 Service 可以设置多个 Connector,但是只能有一个 Container 容器
      • 主要是为了关联 Connector 和 Container,同时会初始化它下面的其它组件
      • Tomcat 中 Service 接口的标准实现类是 StandardService 它不仅实现了 Service 借口同时还实现了 Lifecycle 接口,这样它就可以控制它下面的组件的生命周期了
    • Server
      • Server 要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到这个 Service 集合、同时要维护它所包含的所有 Service 的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的 Service
      • 它的标准实现类 StandardServer 实现了上面这些方法,同时也实现了 Lifecycle、MbeanRegistration 两个接口的所有方法
    • Lifecycle
      • Tomcat 中组件的生命周期是通过 Lifecycle 接口来控制的,组件只要继承这个接口并实现其中的方法就可以统一被拥有它的组件控制了,这样一层一层的直到一个最高级的组件就可以控制 Tomcat 中所有组件的生命周期,这个最高的组件就是 Server,而控制 Server 的是 Startup,也就是您启动和关闭 Tomcat
      • 除了控制生命周期的 Start 和 Stop 方法外还有一个监听机制,在生命周期开始和结束的时候做一些额外的操作
      • Lifecycle 接口的方法的实现都在其它组件中,就像前面中说的,组件的生命周期由包含它的父组件控制,所以它的 Start 方法自然就是调用它下面的组件的 Start 方法,Stop 方法也是一样。如在 Server 中 Start 方法就会调用 Service 组件的 Start 方法
    • Connector
      • Connector 组件是 Tomcat 中两个核心组件之一,它的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程,处理这个请求的线程就是 Container 组件要做的事
      • Connector 是可以选择替换的。Connector 最重要的功能就是接收连接请求然后分配线程让 Container 来处理这个请求,所以这必然是多线程的,多线程的处理是 Connector 设计的核心
      • Connector 划分成 Connector、Processor、Protocol
    • Container
      • Container 是容器的父接口,所有子容器都必须实现这个接口,Container 容器的设计用的是典型的责任链的设计模式
      • 它有四个子容器组件构成,分别是:Engine、Host、Context、Wrapper,这四个组件不是平行的,而是父子关系,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper
      • 通常一个 Servlet class 对应一个 Wrapper,如果有多个 Servlet 就可以定义多个 Wrapper,如果有多个 Wrapper 就要定义一个更高的 Container 了,如 Context
      • Context 还可以定义在父容器 Host 中,Host 不是必须的,但是要运行 war 程序,就必须要 Host,因为 war 中必有 web.xml 文件,这个文件的解析就需要 Host 了,如果要有多个 Host 就要定义一个 top 容器 Engine 了。而 Engine 没有父容器了,一个 Engine 代表一个完整的 Servlet 引擎
      • Valve 的设计在其他框架中也有用的,同样 Pipeline 的原理也基本是相似的,它是一个管道,Engine 和 Host 都会执行这个 Pipeline,您可以在这个管道上增加任意的 Valve,Tomcat 会挨个执行这些 Valve,而且四个组件都会有自己的一套 Valve 集合
    • Engine容器
      • 它的标准实现类是 StandardEngine,这个类注意一点就是 Engine 没有父容器了,如果调用 setParent 方法时将会报错。添加子容器也只能是 Host 类型的
    • Host容器
      • Host 是 Engine 的字容器,一个 Host 在 Engine 中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分它们
      • 它的子容器通常是 Context,它除了关联子容器外,还有就是保存一个主机应该有的信息
      • 所有容器都继承的 ContainerBase 外,StandardHost 还实现了 Deployer 接口,上图清楚的列出了这个接口的主要方法,这些方法都是安装、展开、启动和结束每个 web application
    • Context容器
      • Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host
      • Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,在前面的时序图中就可以发现获取子容器都是通过 request 来分配的
    • Wrapper容器
      • Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收
      • Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错
      • Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道
      • 当装载了 Servlet 后就会调用 Servlet 的 init 方法,同时会传一个 StandardWrapperFacade 对象给 Servlet,这个对象包装了 StandardWrapper
      • Servlet 可以获得的信息都在 StandardWrapperFacade 封装,这些信息又是在 StandardWrapper 对象中拿到的。所以 Servlet 可以通过 ServletConfig 拿到有限的容器的信息
      • 当 Servlet 被初始化完成后,就等着 StandardWrapperValve 去调用它的 service 方法了,调用 service 方法之前要调用 Servlet 所有的 filter
    • 其他组件
      • 安全组件 security、logger 日志组件、session、mbeans、naming 等
  • 顺序:listener -> filter -> servlet
  • Tomcat设计思想和模式
    • Facade外观(门面)模式
      • 接口/类
        • HttpRequestFacade
          • RequestFacade:内部把Request转为ServletReuqest
            • Request <- HttpRequest
            • ServletRequest <- HttpServletRequest
      • HttpRequestFacade 类封装了 HttpRequest 接口能够提供数据,通过 HttpRequestFacade 访问到的数据都被代理到 HttpRequest 中
      • 通常被封装的对象都被设为 Private 或者 Protected 访问修饰,以防止在 Façade 中被直接访问
    • 观察者(监听)模式
      • 控制组件生命周期的 Lifecycle 就是这种模式的体现,还有对 Servlet 实例的创建、Session 的管理、Container 等都是同样的原理
      • 抽象观察者:LifecycleListener,定义一个 lifecycleEvent 方法,这个方法就是当主题变化时要执行的方法
      • 具体的观察者:ServerLifecycleListener,实现了 LifecycleListener 接口的方法
      • 抽象主题:Lifecycle,定义了管理观察者的方法和它要所做的其它方法
      • 具体主题:StandardServer,代表的是具体主题,它实现了抽象主题的所有方法
      • LifecycleEvent:使得可以定义事件类别,不同的事件可区别处理,更加灵活
      • LifecycleSupport:代理了主题对多观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改 LifecycleSupport 类就可以了,不需要去修改所有具体主题,因为所有具体主题的对观察者的操作都被代理给 LifecycleSupport 类了,这可以认为是观察者模式的改进版
    • 命令模式
      • 把 Tomcat 中两个核心组件 Connector 和 Container,比作一对夫妻。男的将接受过来的请求以命令的方式交给女主人。对应到 Connector 和 Container,Connector 也是通过命令模式调用 Container 的
      • 命令模式角色
        • Client:创建一个具体命令(ConcreteCommand)对象并确定其接收者
        • Command 命令:声明了一个给所有具体命令类的抽象接口
        • ConcreteCommand:具体命令,定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操作。execute()方法通常叫做执行方法
        • Invoker 请求者:负责调用命令对象执行请求,相关的方法叫做行动方法
        • Receiver 接受者:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法
      • 命令模式的优点
        • 更松散的耦合
          • 命令模式使得发起命令的对象——客户端,和具体实现命令的对象——接收者对象完全解耦,也就是说发起命令的对象完全不知道具体实现对象是谁,也不知道如何实现
        • 更动态的控制
          • 命令模式把请求封装起来,可以动态地对它进行参数化、队列化和日志化等操作,从而使得系统更灵活
        • 很自然的复合命令
          • 命令模式中的命令对象能够很容易地组合成复合命令,也就是宏命令,从而使系统操作更简单,功能更强大
        • 更好的扩展性
          • 由于发起命令的对象和具体的实现完全解耦,因此扩展新的命令就很容易,只需要实现新的命令对象,然后在装配的时候,把具体的实现对象设置到命令对象中,然后就可以使用这个命令对象,已有的实现完全不用变化
      • Tomcat命令模式
        • Connector 作为抽象请求者(Invoker )
        • HttpConnector 作为具体请求者(Invoker )
        • HttpProcessor 作为命令(Command)
        • Container 作为命令的抽象接受者(Receiver)
        • ContainerBase 作为具体的接受者(Receiver)
        • 客户端就是应用服务器 Server 组件了(Client)
      • Server 首先创建命令请求者 HttpConnector 对象,然后创建命令 HttpProcessor 命令对象。再把命令对象交给命令接受者 ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的 Container 执行的。命令可以以队列的方式进来,Container 也可以以不同的方式来处理请求,如 HTTP1.0 协议和 HTTP1.1 的处理方式就会不同
    • 责任链(Chain of Responsibility )模式
      • 说明
        • 责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求
        • 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任
        • 责任链可能是一条直线、一个环链或者一个树结构的一部分
      • 结构
        • 抽象处理者(Handler)角色定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作
        • 具体处理者(ConcreteHandler)角色具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家
      • 适用场景
        • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
        • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
        • 处理一个请求的对象集合应被动态指定
      • 跟命令模式区别
        • 职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者
      • 在 Tomcat 中这种设计模式几乎被完整的使用,tomcat 的容器设置就是责任链模式,从 Engine 到 Host 再到 Context 一直到 Wrapper 都是通过一个链传递请求
1 0
原创粉丝点击