`
gearever
  • 浏览: 149388 次
社区版块
存档分类
最新评论

tomcat架构分析(容器类)

阅读更多

出处:http://gearever.iteye.com 

 

Tomcat提供了engine,host,context及wrapper四种容器。在总体结构中已经阐述了他们之间的包含关系。这四种容器继承了一个容器基类,因此可以定制化。当然,tomcat也提供了标准实现。

  • Engine:org.apache.catalina.core.StandardEngine
  • Host: org.apache.catalina.core.StandardHost
  • Context:org.apache.catalina.core.StandardContext
  • Wrapper:org.apache.catalina.core.StandardWrapper


所谓容器,就是说它承载了若干逻辑单元及运行时数据。好比,整个酒店是一个容器,它包含了各个楼层等设施;每个楼层也是容器,它包含了各个房间;每个房间也是容器,它包含了各种家电等等。
首先来看一下容器类的类结构。

基类ContainerBase
ContainerBase是个abstract基类。其类路径为:

org.apache.catalina.core.ContainerBase


这里只列出一些比较核心功能的组件及方法。需要注意的是,类中的方法及属性很多,限于篇幅不全部列出来了。
Enigne
Engine是最顶层的容器,它是host容器的组合。其标准实现类为:

org.apache.catalina.core.StandardEngine


看一下StandardEngine的主要逻辑单元概念图。

从图中可以看出,engine有四大组件:

  • Cluster: 实现tomcat集群,例如session共享等功能,通过配置server.xml可以实现,对其包含的所有host里的应用有效,该模块是可选的。其实现方式是基于pipeline+valve模式的,有时间会专门整理一个pipeline+valve模式应用系列;
  • Realm:实现用户权限管理模块,例如用户登录,访问控制等,通过通过配置server.xml可以实现,对其包含的所有host里的应用有效,该模块是可选的;
  • Pipeline:这里简单介绍下,之后会有专门文档说明。每个容器对象都有一个pipeline,它不是通过server.xml配置产生的,是必须有的。它就是容器对象实现逻辑操作的骨架,在pipeline上配置不同的valve,当需要调用此容器实现逻辑时,就会按照顺序将此pipeline上的所有valve调用一遍,这里可以参考责任链模式;
  • Valve:实现具体业务逻辑单元。可以定制化valve(实现特定接口),然后配置在server.xml里。对其包含的所有host里的应用有效。定制化的valve是可选的,但是每个容器有一个缺省的valve,例如engine的StandardEngineValve,是在StandardEngine里自带的,它主要实现了对其子host对象的StandardHostValve的调用,以此类推。


配置的例子有:

<Engine name="Catalina" defaultHost="localhost">   
  <Valve className="MyValve0"/>   
  <Valve className="MyValve1"/>   
  <Valve className="MyValve2"/>   
  ……   
  <Host name="localhost" appBase="webapps"> 
  </Host>
</Engine>


需要注意的是,运行环境中,pipeline上的valve数组按照配置的顺序加载,但是无论有无配置定制化的valve或有多少定制化的valve,每个容器缺省的valve,例如engine的StandardEngineValve,都会在数组中最后一个。
Host
Host是engine的子容器,它是context容器的集合。其标准实现类为:

org.apache.catalina.core.StandardHost


StandardHost的核心模块与StandardEngine差不多。只是作用域不一样,它的模块只对其包含的子context有效。除此,还有一些特殊的逻辑,例如context的部署。Context的部署还是比较多的,主要分为:

  • War部署
  • 文件夹部署
  • 配置部署等

有时间单独再说吧。照例贴个核心模块概念图。

Context
Context是host的子容器,它是wrapper容器的集合。其标准实现类为:

org.apache.catalina.core.StandardContext


应该说StandardContext是tomcat中最大的一个类。它封装的是每个web app。
看一下StandardContext的主要逻辑单元概念图。

Pipeline,valve,realm与上面容器一样,只是作用域不一样,不多说了。

  • Manager: 它主要是应用的session管理模块。其主要功能是session的创建,session的维护,session的持久化(persistence),以及跨context的session的管理等。Manager模块可以定制化,tomcat也给出了一个标准实现;
org.apache.catalina.session.StandardManager


manager模块是必须要有的,可以在server.xml中配置,如果没有配置的话,会在程序里生成一个manager对象。

  • Resources: 它是每个web app对应的部署结构的封装,比如,有的app是tomcat的webapps目录下的某个子目录或是在context节点配置的其他目录,或者是war文件部署的结构等。它对于每个web app是必须的。
  • Loader:它是对每个web app的自有的classloader的封装。具体内容涉及到tomcat的classloader体系,会在一篇文档中单独说明。Tomcat正是有一套完整的classloader体系,才能保证每个web app或是独立运营,或是共享某些对象等等。它对于每个web app是必须的。
  • Mapper:它封装了请求资源URI与每个相对应的处理wrapper容器的映射关系。


以某个web app的自有的web.xml配置为例;

<servlet>
  <servlet-name>httpserver</servlet-name>
  <servlet-class>com.gearever.servlet.TestServlet</servlet-class>
</servlet>
 
<servlet-mapping>
  <servlet-name>httpserver</servlet-name>
  <url-pattern>/*.do</url-pattern>
</servlet-mapping>


对于mapper对象,可以抽象的理解成一个map结构,其key是某个访问资源,例如/*.do,那么其value就是封装了处理这个资源TestServlet的某个wrapper对象。当访问/*.do资源时,TestServlet就会在mapper对象中定位到。这里需要特别说明的是,通过这个mapper对象定位特定的wrapper对象的方式,只有一种情况,那就是在servlet或jsp中通过forward方式访问资源时用到。例如,

request.getRequestDispatcher(url).forward(request, response)


关于mapper机制会在一篇文档中专门说明,这里简单介绍一下,方便理解。如图所示。

Mapper对象在tomcat中存在于两个地方(注意,不是说只有两个mapper对象存在),其一,是每个context容器对象中,它只记录了此context内部的访问资源与相对应的wrapper子容器的映射;其二,是connector模块中,这是tomcat全局的变量,它记录了一个完整的映射对应关系,即根据访问的完整URL如何定位到哪个host下的哪个context的哪个wrapper容器。
这样,通过上面说的forward方式访问资源会用到第一种mapper,除此之外,其他的任何方式,都是通过第二种方式的mapper定位到wrapper来处理的。也就是说,forward是服务器内部的重定向,不需要经过网络接口,因此只需要通过内存中的处理就能完成。这也就是常说的forward与sendRedirect方式重定向区别的根本所在。
看一下request.getRequestDispatcher(url) 方法的源码。

public RequestDispatcher getRequestDispatcher(String path) { 

  // Validate the path argument 
  if (path == null) 
    return (null); 
  if (!path.startsWith("/")) 
    throw new IllegalArgumentException 
     (sm.getString 
        ("applicationContext.requestDispatcher.iae", path)); 

  // Get query string 
  String queryString = null; 
  int pos = path.indexOf('?'); 
  if (pos >= 0) { 
    queryString = path.substring(pos + 1); 
    path = path.substring(0, pos); 
  } 

  path = normalize(path); 
  if (path == null) 
    return (null); 

  pos = path.length(); 

  // Use the thread local URI and mapping data 
  DispatchData dd = dispatchData.get(); 
  if (dd == null) { 
    dd = new DispatchData(); 
    dispatchData.set(dd); 
  } 

  MessageBytes uriMB = dd.uriMB; 
  uriMB.recycle(); 

  // Use the thread local mapping data 
  MappingData mappingData = dd.mappingData; 

  // Map the URI 
  CharChunk uriCC = uriMB.getCharChunk(); 
  try { 
    uriCC.append(context.getPath(), 0, context.getPath().length()); 
  /* 
  * Ignore any trailing path params (separated by ';') for mapping 
  * purposes 
  */ 
    int semicolon = path.indexOf(';'); 
      if (pos >= 0 && semicolon > pos) { 
      semicolon = -1; 
    } 
    uriCC.append(path, 0, semicolon > 0 ? semicolon : pos); 
    context.getMapper().map(uriMB, mappingData); 
    if (mappingData.wrapper == null) { 
      return (null); 
    } 
    /* 
    * Append any trailing path params (separated by ';') that were 
    * ignored for mapping purposes, so that they're reflected in the 
    * RequestDispatcher's requestURI 
    */ 
    if (semicolon > 0) { 
      uriCC.append(path, semicolon, pos - semicolon); 
    } 
  } catch (Exception e) { 
   // Should never happen 
   log(sm.getString("applicationContext.mapping.error"), e); 
   return (null); 
  } 

  Wrapper wrapper = (Wrapper) mappingData.wrapper; 
  String wrapperPath = mappingData.wrapperPath.toString(); 
  String pathInfo = mappingData.pathInfo.toString(); 

  mappingData.recycle(); 

  // Construct a RequestDispatcher to process this request 
  return new ApplicationDispatcher 
      (wrapper, uriCC.toString(), wrapperPath, pathInfo, 
          queryString, null); 

}


红色部分标记了从context的mapper对象中定位wrapper子容器,然后封装在一个dispatcher对象内并返回。通过上面的阐述,也说明了为什么forward方法不能跨context访问资源了。

Wrapper
Wrapper是context的子容器,它封装的处理资源的每个具体的servlet。其标准实现类为:

org.apache.catalina.core.StandardWrapper


应该说StandardWrapper是tomcat中比较重要的一个类。初认识它时,比较容易混淆。
先看一下StandardWrapper的主要逻辑单元概念图。

Pipeline,valve与上面容器一样,只是作用域不一样,不多说了。
主要说说servlet对象与servlet stack对象。这两个对象在wrapper容器中只存在其中之一,也就是说只有其中一个不为空。当以servlet对象存在时,说明此servlet是支持多线程并发访问的,也就是说不存在线程同步的过程,此wrapper容器中只包含一个servlet对象(这是我们常用的模式);当以servlet stack对象存在时,说明servlet是不支持多线程并发访问的,每个servlet对象任一时刻只有一个线程可以调用,这样servlet stack实现的就是个简易的线程池,此wrapper容器中只包含一组servlet对象,它的基本原型是worker thread模式实现的。
那么,怎么来决定是以servlet对象方式存储还是servlet stack方式存储呢?其实,只要在开发servlet类时,实现一个SingleThreadModel接口即可。
如果需要线程同步的servlet类,例如:

public class LoginServlet extends HttpServlet implements javax.servlet.SingleThreadModel{ …… }


但是值得注意的是,这种同步机制只是从servlet规范的角度来说提供的一种功能,在实际应用中并不能完全解决线程安全问题,例如如果servlet中有static数据访问等,因此如果对线程安全又比较严格要求的,最好还是用一些其他的自定义的解决方案。

Wrapper的基本功能已经说了。那么再说一个wrapper比较重要的概念。严格的说,并不是每一个访问资源对应一个wrapper对象。而是每一种访问资源对应一个wrapper对象。其大致可分为三种:

  • 处理静态资源的一个wrapper:例如html,jpg等静态资源的wrapper,它包含了一个tomcat的实现处理静态资源的缺省servlet:

 

org.apache.catalina.servlets.DefaultServlet

 

  • 处理jsp的一个wrapper:例如访问的所有jsp文件,它包含了一个tomcat的实现处理jsp的缺省servlet:

 

org.apache.jasper.servlet.JspServlet


它主要实现了对jsp的编译等操作

  • 处理servlet的若干wrapper:它包含了自定义的servlet对象,就是在web.xml中配置的servlet。


需要注意的是,前两种wrapper分别是一个,主要是其对应的是DefaultServlet及JspServlet。这两个servlet是在tomcat的全局conf目录下的web.xml中配置的,当app启动时,加载到内存中。

<servlet>
  <servlet-name>default</servlet-name>
  <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
  <init-param>
    <param-name>debug</param-name>
    <param-value>0</param-value>
  </init-param>
  <init-param>
    <param-name>listings</param-name>
    <param-value>false</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
 
<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
  <init-param>
    <param-name>fork</param-name>
    <param-value>false</param-value>
  </init-param>
  <init-param>
    <param-name>xpoweredBy</param-name>
    <param-value>false</param-value>
  </init-param>
  <load-on-startup>3</load-on-startup>
</servlet>


至此,阐述了tomcat的四大容器结构。 有时间接着探讨tomcat如何将这四大容器串起来运作的。

 

分享到:
评论

相关推荐

    tomcat 架构 分析

    Tomcat架构具有模块化特性,其核心部分由两个组件构成:Connector(连接器)和Container(容器)。这两者在Tomcat中扮演着极其重要的角色。Connector组件负责接收客户端的请求,它在Tomcat架构中可替换,这意味着...

    Tomcat架构解析文档.zip

    【Java面试必备】Tomcat架构解析 Tomcat作为一款开源的、基于Java的Web应用服务器,是许多初学者和开发者入门Java Web应用的首选。它轻量级、高效且易于管理,广泛应用于小型到中型企业级应用。在面试中,对Tomcat...

    tomcat架构的源码分析

    ### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...

    tomcat架构解析_PDF电子书下载 高清 带索引书签目录_刘光瑞(著)

    《Tomcat架构解析》这本书由刘光瑞撰写,由人民邮电出版社出版,是一本深入探讨Tomcat服务器架构的专业书籍。Tomcat作为Apache软件基金会的项目之一,是世界上最流行的Java应用服务器,尤其在轻量级Web应用领域,其...

    tomcat 架构解析和优化。pdf

    《Tomcat架构解析与优化》一书主要涵盖了Apache Tomcat服务器的基础架构、工作原理以及性能调优策略。Tomcat作为一款广泛使用的Java Servlet容器,它的高效运行和优化对于任何Java Web应用都至关重要。 首先,...

    tomcat架构解析 【刘光瑞PDF高清】.rar

    《Tomcat架构解析》是由刘光瑞撰写的一本深入探讨Tomcat应用服务器架构的专业书籍。这本书全面剖析了Tomcat的设计原理、内部工作机制以及各种组件的详细配置,是学习和理解Tomcat不可或缺的参考资料。 Tomcat作为一...

    Tomcat 架构 原理

    《Tomcat架构原理》深入解析 一、Tomcat架构概览 Apache Tomcat是一个开源的Servlet容器,由Apache软件基金会的Jakarta项目提供。它主要实现了Servlet和JavaServer Pages(JSP)技术规范,同时也提供了HTTP服务器...

    tomcat 架构解析

    **Tomcat架构解析** Tomcat是一款广泛使用的开源Java Servlet容器,由Apache软件基金会开发和维护。它是Java EE(现在称为Jakarta EE)平台的核心部分,主要用于托管Web应用程序。本篇文章将深入探讨Tomcat的架构,...

    tomcat嵌入OSGI容器

    标题中的“tomcat嵌入OSGI容器”是指在Apache Tomcat服务器中集成OSGI(Open Service Gateway Initiative)框架,使得Tomcat能够支持模块化的应用程序部署和管理。OSGI是一种Java平台上的服务导向架构,它允许动态地...

    tomcat 源码分析系列文档

    【标题】"Tomcat源码分析系列文档"深入解析了Apache Tomcat服务器的内部工作原理,涵盖了一系列关键知识点,如HTTP协议、类加载机制、容器设计模式等。这些文档为理解Tomcat的运行机制提供了宝贵的资源。 【描述】...

    Tomcat_系统架构与模式设计分析.doc

    《Tomcat系统架构与模式设计分析》 Tomcat,作为一款广泛应用的Java Servlet容器,其系统架构和模式设计对于理解其高效稳定运行至关重要。本文将深入探讨Tomcat的核心组件、结构以及关键设计模式。 首先,Tomcat的...

    TOMCAT架构服务器优化指南

    《TOMCAT架构服务器优化指南》是一本深入探讨TOMCAT服务器优化的专业书籍,由刘光瑞撰写,并由人民邮电出版社出版。该书聚焦于如何提升TOMCAT服务器的性能,确保系统的稳定性和高效运行。TOMCAT作为一款广泛应用的...

    tomcat架构解析_PDF电子书下载 高清

    《Tomcat架构解析》这本书深入探讨了Apache Tomcat这一广泛使用的Java Servlet容器的内部机制和工作原理。Tomcat是开源的、轻量级的应用服务器,主要用于运行Java Web应用程序,包括Servlet和JSP。理解其架构对于...

    tomcat架构解析.zip

    **Tomcat架构解析** Tomcat是一款广泛使用的开源Java Servlet容器,它是Apache软件基金会下的Jakarta项目的一部分。Tomcat实现了Java Servlet和JavaServer Pages(JSP)规范,为Web应用程序提供了运行环境。本篇将...

    架构解析——Tomcat

    3. ** Jasper**:是Tomcat中的JSP引擎,负责将JSP页面编译为Java类。Jasper提供了动态编译和热部署功能,使得JSP页面的修改无需重启服务器即可生效。 4. **Juli**:是Tomcat的日志系统,允许自定义日志配置,提供...

    01-Tomcat架构解析1

    【Tomcat架构解析】 Tomcat是一款广泛使用的开源Java Servlet容器,它是Apache软件基金会下的Jakarta项目的一部分。在本文中,我们将深入探讨Tomcat的核心架构、关键组件及其工作流程。 **一、Tomcat架构** ...

    Tomcat架构

    《深入解析Tomcat架构》 Tomcat,作为Java EE领域广泛应用的开源Web服务器和Servlet容器,其内部架构的复杂性和灵活性使其成为开发者的得力工具。本文将详细探讨Tomcat的核心组件及其工作原理,帮助读者深入理解其...

    how tomcat works——(5)容器

    Tomcat的源码组织清晰,通过跟踪ContainerBase、StandardEngine、StandardHost、StandardContext等类,我们可以看到容器的实现细节,这对于优化性能或定制功能非常有用。 总结,Tomcat的容器机制是其核心架构的一...

    tomcat源码+文档pdf+源码解析

    Tomcat是Apache软件基金会下的一个开源项目,是一个广泛使用的Java Servlet容器,实现了Servlet和JavaServer Pages(JSP)规范,使开发者能够构建和部署Web应用程序。这个资源包包含了Tomcat的源码、文档以及源码...

    S19-再看tomcat架构与请求处理流程1

    本文将深入探讨 Tomcat 的架构和请求处理流程。 首先,Tomcat 作为一个 HTTP 服务器,其核心功能之一是通过 Socket 进行网络通信,遵循 TCP/IP 协议。Socket 提供了应用程序之间进行低级别网络通信的接口,使得 ...

Global site tag (gtag.js) - Google Analytics