Tomcat架构(三)

嵌套组件

这些组件是针对Tocmat做的特定实现,他们的主要目的是使各种Tomcat容器可以完成各自的工作。

1、阀(Valve)

valve是处理元素,它可以被包含在每个Tomcat容器的处理路径中--如engine、host、context以及servelt包装器。若要增加Valve到Tomcat容器则需要在server.xml中使用<Valve>标签。在server.xml中这些标签的执行顺序与其物理顺序相同。

而在Tomcat中也分布这大量预先编译好的valve。包括:

?在请求日志元素中将请求(如远程客户端ip地址)写入日志文件或数据库时

?根据远程客户端ip或主机名来控制某一特定web应用的访问权限时

?记录每个请求和响应头信息日志时

?在同一个虚拟主机下为多个应用配置单点登录时

如果以上这些都不能满足你的要求,那么你可以通过继承org.apache.catalina.Valve来实现自定义的Valve并将其配置到对应服务中。

但是对于一个容器来说,它并不会持有某个单独valve的引用;相反,它会持有一个称作管道(Pipeline)的单一实体的引用,并用这个管道来表示与该容器所关联的一系列valve。

当一个容器被调用来处理一个请求时,它会委托与其关联的管道来处理对应请求。

在管道中,这些valve则是基于他们在server.xml中的定义作顺序排列。其中排在队列中排在最后的valve被称为管道的基本valve,该valve用来完成去执行容器的核心功能的任务。

与单个valve不同,管道在server . xml不是一个明确的元素,而是含蓄的按照valve在给定容器中所定义的顺序组成。

并且在管道中,每个valve都知道其下一个valve;在它执行完前置处理以后,接下来它会调用链中的下一个valve,当该调用返回以后,它会在return之前执行他自身的处理任务。

这种方式和servlet规范中的过滤器链所做的事情非常相似。

在这幅图中,当接收到传入请求时引擎所配置的valve首先被触发。其中引擎中基本的valve负责确定目标主机委托该主机来处理;接下来目标主机(www.host1.com)的valve被按顺序触发。而该主机的基本valve则又决定了目标context(在这里是Context1)并且委托该context来处理该请求。最后Context1中所配置的valve被触发,然后通过context中配置的基本valve委托给适当的包装器来处理;而包装器的基本valve又将处理转交至被包装的servlet来处理。

处理完成以后,响应结果会按照以上的路径反方向返回。

由于Valve就成了Tomcat服务器实现中的一部分,并且可以为开发者提供一种方式将自定义的代码注入到处理请求的servlet容器中。因此,自定的valve类文件需要发布到CATALINA_HOME/lib目录下而不是应用的发布目录WEB-INF/classes。

由于它们并不是servlet规范中的部分,所以valve在企业级一用中属于不可移植元素。因此,如果已经依赖了一个特定的valve时,你必须在不同的应用服务器上找到对等的选择方案。

还有很重要的一点就是,为了不影响请求处理的效率必须要保证valve的代码高效执行。

2、Realm

容器管理安全方面的工作通过容器处理应用程序的身份验证和授权方面来解决。

身份验证存在的主要任务就是确保用户所说的就是她自己,而授权的主要任务是决定一个用户是否可以在某个应用下执行特定操作。

由容器来管理安全的优势是可以通过应用的发布者直接来配置安全措施。也就是说,为用户分配密码以及为用户分配角色都可以用户配置来完成,而这些配置也可以在修改任何代码的情况下来供多个web应用共用。

应用管理安全

还有一种可选方案就是通过应用来管理安全问题。这种情况下,我的web应用程序代码就是唯一的仲裁者来决定用户在我们的应用下是否有访问特定功能或资源的权限。

想要使容器来管理安全问题起作用,我们需要组装一下组件:

?安全约束:在我们的web应用部署描述器web.xml中,我们必须确定限制资源访问的url表达式以及可以访问这些资源的用户角色。

?凭证输入机制:在web.xml部署文件中,我们需要指定容器应该如何提示用户通过凭证来验证。这通常是通过弹出一个对话框提示用户输入用户名和密码来完成,但也可以配置使用其他机制,如一个定制的登录表单等。

?Realm:这是一个数据存储机制来保存用户名、密码以及角色来对用户所提供的凭证信息进行检查。它可以是一个简单的xml文件,一个通过JDBC API来访问的关系型数据库中的一张表或者是可以通过JNDI API访问的轻量级目录访问协议服务器(LDAP)。正是Realm为Tomcat提供了一致的访问机制来访问这些不同的数据源。

以上这三种组件在技术上是相互独立的。基于容器安全的威力就在于我们可以根据我们自身的安全情况从这几种方式中选出适合的一种或几种方式来混合使用。

至此,当一个用户请求一个资源时,Tomcat将检查对所请求的资源是否已经存在了安全限制。对于存在限制的资源,Tomcat将自动要求用户提供身份凭证并通过所配置的Realm来检查用户所提供凭证是否符合。只有在用户所提供的凭证信息通过了验证或者用户的角色在可访问资源的配置之列才能访问对应资源。

3、执行器

这是从tomcat 6.0.11版本开始,新增的一个组件。此组件允许您配置一个共享的线程池,以供您的连接器使用。您的连接器可能使并发线程的数量达到上限。请注意,此限制同样适用于:即使一个特定的连接器没有用完为它配置的所有线程。

4、监听器

每个主要的tomcat组件都实现了org.apache.catalina.Lifecycle接口。实现了该接口的组件注册到监听器,然后该组件的生命周期事件被触发,比如该组件的启动和停止都会被监听。一个监听器实现了org.apache.catalina.LifecycleListener接口,也实现了该接口的lifecycleEvent()方法,监听器捕捉到一个LifecycleEvent 表示事件已经发生。这就给您提供了一个机会:把您自定义的进程注入到tomcat的生命周期。

5、会话管理器

会话让使用无状态HTTP协议的应用程序完成通信。会话表示客户端和服务器之间的通信,会话功能是由javax.servlet.http.HttpSession 的实例实现的,该实例存储在服务器上而且与一个唯一的标识符相关联,客户端在与服务器的每次交互中根据请求中的标识符找到它的会话。一个新的会话在客户端请求后被创建,会话一直有效直到一段时间后客户端连接超时,或者会话直接失效例如客户退出访问服务器。

上图显示了一个非常简单的 tomcat 会话机制视图。Catalina 引擎(engine)使用了组件org.apache.catalina.Manager
去创建、查找、注销会话。该组件负责管理为上下文创建的会话以及会话的生命周期。会话管理器(Manager)把会话存放在内存中,但是它支持在服务器重启时恢复会话。当服务器停止时,会话管理器把所有活动的会话写入磁盘,当服务器重新启动时把会话重新加载到内存。

一个<Manager>必须是 <Context>的子节点,而且<Manager>负责管理与web应用程序上下文相关的会话。

会话管理器管理这样的属性:例如用来生成会话标识符的算法,每秒钟检查过期会话的频率,支持的活动会话的最大数目,以及持久化会话的文件。

会话管理器实现了这样的功能:为会话提供持久化存储,例如一个文件或一个JDBC数据库。

6、加载器

这个组件是一个给定的web应用程序的类加载器。Java中的类加载器是一个神秘的实体。简而言之,类加载器负责加载、解释Java类编译后的字节码。

一个Java类的字节码可能存放在各种不同的位置,最常见的是在本地文件系统或网络中。类加载器的主要任务是:抽象字节如何被获取以及如何重组到内存中的类的过程。

7、委托(代理)模型

自从Java 2以来,类加载机制使用了委托模型,JVM中的类加载器被组织成了父---子层次结构。据介绍,每个类加载器首先把查找和加载一个类的任务委托给它的父级,在它自己尝试做这个任务之前。

这种委托机制确保:没有应用程序可以加载一个有恶意的系统类(例如java.lang.Object),它可能危及在JVM中运行的应用程序的完整性。

类加载器层次结构的顶层是Bootstrap 类加载器,它也叫原始类加载器,它是原生代码而且是JVM的一部分。作为JVM的一部分可以保证:至少有一个可以依靠的类加载器,去加载Java的核心类(例如java.lang.Object)。这个类加载器(Bootstrap
)负责从Java核心包(例如java.lang 或 java.util)里加载类文件。在SUN的JVM中,这些核心类文件存放在JAVA_HOME/jre/lib/rt.jar 。Bootstrap类加载器的独特之处在于:它是层次结构树的根节点,因此它没有父类加载器。

层次结构的下一层是Extension类加载器,它在SUN的JVM中是一个java.net.URLClassLoader,它监控JAVA_HOME/jre/lib/ext 文件夹扩展JARs 。放在此文件夹下的任何JARs(包括类路径之外的)都会被自动加载。

层次结构最底层是系统类加载器(应用程序类加载器),它在SUN的JVM中也是一个URLClassLoader 。它监控CLASSPATH里描述的文件夹、JARs 。这个类加载器负责加载应用程序的主类。

如果一个普通的应用程序需要加载一个类(例如java.lang.String),它首先会询问应用程序类加载器去加载那个类。应用程序类加载器会委托给它的父级Extension类加载器,Extension类加载器委托给它的父级Bootstrap 类加载器,Bootstrap 类加载器然后在rt.jar里加载String.class文件并且使它成为一个可用的java.lang.Class实例。

如果需要加载一个应用程序特定的类文件(例如com.swengsol.UserModel.class),那么委托过程和前面一样。然而这次,Bootstrap 类加载器在rt.jar里没能加载到此类文件,现在轮到Extension类加载器同样没能加载到此类文件。最后,应用程序类加载器在CLASSPATH里找到了此类文件。然后这个类文件被加载并成为一个JVM可以使用的实例。

每个类加载器里都有缓存,所以每个类加载器首先要检查自己的缓存看是否已经加载了类文件。如果找到了,则直接返回类文件。

在我们前面的示例中,如果应用程序需要另一个String类,那么Bootstrap 类加载器则直接返回在它缓存里的String类实例。

未完待续......

1. 本文由程序员学架构翻译

2. 本文译自

https://www.packtpub.com/books/content/overview-tomcat-6-servlet-container-part-2

3. 转载请务必注明本文出自:程序员学架构(微信号:archleaner)

4. 更多文章请扫码:

时间: 2024-10-18 10:07:36

Tomcat架构(三)的相关文章

tomcat架构分析 (connector NIO 实现)

出处:http://gearever.iteye.com 上一篇简单记录了缺省配置的connector的内部构造及消息流,同时此connector也是基于BIO的实现.除了BIO外,也可以通过配置快速部署NIO的connector.在server.xml中如下配置: Xml代码 <Connector port="80" URIEncoding="UTF-8" protocol="org.apache.coyote.http11.Http11NioPr

tomcat架构分析(概览)

出处:http://gearever.iteye.com Tomcat是目前应用比较多的servlet容器.关于tomcat本身的特点及介绍,网上已经有很多描述了,这里不再赘述.Tomcat除了能够支撑通常的web app外,其本身高度模块化的架构体系,也能带来最大限度的可扩展性.目前tomcat版本已经衍生到tomcat7,但是主流的版本还是tomcat6.此系列架构体系介绍还是以tomcat6为蓝本. Tomcat是有一系列逻辑模块组织而成,这些模块主要包括: 核心架构模块,例如Server

使用docker部署nginx+tomcat架构(3):使用docker-compose简化部署操作

经历了之前的两篇,我们已经大体上了解了docker部署容器的过程. 使用docker部署nginx+tomcat架构 使用docker部署nginx+tomcat架构(2):访问mysql数据库 不过,整个部署过程中需要手动输入很多的docker命令,稍显繁琐并且容易出错.那么有没有一种相对简洁优雅的方式来完成这些部署工作呢?答案是有的,docker-compose(一下简称“compose”)正是为此而生. 关于docker-compose(了解更多:https://docs.docker.c

tomcat架构解析:Catalina+Coyote+Jasper+配置管理+集群+调优等

在目前流行的互联网架构中,对一个应用来说,Tomcat是首,SSM是中,JVM是尾,我们通常对于SSM是比较了解的,而忽略了首尾,而Tomcat在目前的网络编程中是举足轻重的,但是我们其实对Tomcat中很多原理性的东西不太了解,如果能够掌握Tomcat的原理,那么是非常有用的,比如: 如果我们能弄清楚Tomcat和Socket.Tcp之间的关系,我们就能明白Tomcat为什么会出现端口冲突.如果我们能准确的知道Tomcat中部署一个项目的N种方式,那么就能在工作中更加得心应手.Tomcat中热

终于有人把tomcat讲清楚了!阿里大牛推荐的tomcat架构解析文档

在目前流行的互联网架构中,对一个应用来说,Tomcat是首,SSM是中,JVM是尾,我们通常对于SSM是比较了解的,而忽略了首尾,而Tomcat在目前的网络编程中是举足轻重的,但是我们其实对Tomcat中很多原理性的东西不太了解,如果能够掌握Tomcat的原理,那么是非常有用的,比如: 如果我们能弄清楚Tomcat和Socket.Tcp之间的关系,我们就能明白Tomcat为什么会出现端口冲突.如果我们能准确的知道Tomcat中部署一个项目的N种方式,那么就能在工作中更加得心应手.Tomcat中热

Tomcat架构以及理解sever.xml

Tomcat架构图 当用户在地址栏输入访问地址后,首先识别访问协议(假设为http),那么通过针对于http协议传输的Connector连接器,连接到tomcat的服务中,连接后开始检测Engine下的host主机名中有无匹配项,如果有,通过appBase找到目标文件夹,然后开始访问相应的html文件等:如果没匹配到,执行<Engine name="Catalina" defaultHost="localhost">这一默认匹配项进行默认匹配. 理解se

将项目部署到tomcat的三种方法

2014年8月初8    星期五 又到星期五了,可以轻松的敲点东西,不担心睡太晚起不来,或者起来后上班打瞌睡. 由于近期学习了solr相关的知识,部署solr项目到tomcat上的方式很多,包括官方的等.我自己也找了中非官方的方法,感觉很好.而且以前用MyEclipse开发,出错很少,现在用Eclipse所以部署项目后在后台调用user.dir的时候出错,试了一下午也没事出来,而且越试越想试,但是带我的人不让我弄了,他帮我弄,让我干其他任务,我都怀疑是不是他也和我一样就喜欢干这种事情,所以自己去

Tomcat 学习进阶历程之Tomcat架构与核心类分析

前面的http及socket两部分内容,主要是为了后面看Tomcat源码而学习的一些网络基础.从这章开始,就开始实际深入到Tomcat的'内在'去看一看. 在分析Tomcat的源码之前,准备先看一下Tomcat的架构与一些核心类的简单分析,并简单介绍一下Tomcat是如何处理一次Http请求的.这部分内容有相当一部分来源于网络,在此,感谢原作者的贡献. Tomcat的总体架构 Tomcat的架构关系可以从Tomcat的配置文件server.xml中看到端倪. 从上图中可以看出Tomcat 的心脏

Tomcat架构(四)

8.标准覆盖机制 J2SE 1.4 and 1.5 都包含了一个XML处理解析器的Java API .Bootstrap 类加载器加载这个解析器的类文件,所以这个解析器会优先于任何一个安装在CLASSPATH里的解析器 被加载,即使您已经安装了新版本的解析器.标准覆盖机制允许您重写JAVA_HOME/lib/endorsed文件夹里某些特定的类(例如CORBA 和 JAXP 类).Bootstrap 类加载器将会优先加载这些类.想详细了解此机制,请访问http://java.sun.com/j2

tomcat架构分析-索引

tomcat架构分析 (概览) tomcat架构分析 (容器类) tomcat架构分析 (valve机制) tomcat架构分析 (valve源码导读) tomcat架构分析 (Session管理) tomcat架构分析 (JNDI配置) tomcat架构分析 (JNDI体系绑定) tomcat架构分析 (connector BIO 实现) tomcat架构分析 (connector NIO 实现)