服务器 : Apache Tomcat - 理解架构层次

文章概览

  相信很多接触java的人都对Tom猫有着多少的熟悉,就个人而言,本来只知道Tom简单的操作与配置,就像裹上一层纱,迷迷糊糊的.

  Tomcat的书籍本来就不多,高分的还是很久之前的版本,直到最近看到下面这本书,解答了我的很多疑问,同时这篇文章将总结读书收获.

  如果觉得文章写的内容是你感兴趣的或者我的猫使你感兴趣,建议你读读这本书.

  

  该文会介绍Tom的架构,服务器如何从一层层抽象设计到完整的架构

Tomcat介绍

  Tom是一款全世界著名的轻量级应用服务器,基于java,服务于java.主要作为应用服务器来处理客户端发来的动态资源响应.

  目前版本是9.x,很多人都在使用6.x,但新版其实提供了很多新的功能,比如WebSocket的支持,点击了解WebSocket.

    

  Tomcat启动参数

    windows修改$CATALINA_HOME/bin/catalina.bat文件

    Set JAVA_OPTS=-server -Xms1024m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m

    linux修改$CATALINA_HOME/bin/catalina.sh文件

    JAVA_OPTS="-server -Xms1024m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m"

    -server  Server端启动Tomcat,Client启动Tomcat两者的初始化参数会有所不同

    -Xms1024m 初始化堆内存大小

    -Xmx2048m 允许的最大堆内存大小

    -XX:PermSize=256m 初始化非堆内存大小

    -XX:MaxPermSize=512m 允许的最大非堆内存大小

  Debug方式

    依赖于JDK提供的JPDA(Java Platform Debugger Architecture,Java平台调试体系)

    catalina jpda start

  目录结构

    

    该文使用的版本是apache-tomcat-9.0.1,目录大致都很容易理解.

    conf放置的Tomcat的核心配置文件,下文会介绍.

    webapps是默认的web app的应用目录,只要把项目目录放置进去就可以运行

    work是Tomcat运行时产生的jsp编译文件所存放的位置

总体架构

  Tomcat是一款应用服务器,我们从最根本的类一层一层演变,直至Tomcat当前版本.

1.应用服务器是接收其他计算机(客户端)发来的请求数据并对其解析,完成相关业务处理,然后把处理结果作为响应返回给计算机.

  

2.一个问题摆在眼前,前面Server请求监听和请求处理放在一起,应用服务器通常会与web服务器进行集群部署和负载均衡,但是这两者的协议并不是HTTP.

也就是说,服务器连接的另一端需要适配不同的协议来对请求作出不同的处理.前面的模型扩展性太差,应该分离请求监听和请求处理.

Connector模块管理请求监听,Container模块负责请求处理,两个组件都拥有start()和stop()来加载和释放自己维护的资源.

这样子,Server下可以有多个Connector来传送请求至不同的Container中.

3.上面的设计有个缺陷,既然server可以有多个Connector和Container,那么如何知道哪个Connector将请求发至哪个Container呢?

考虑一下下面这个设计图,

4.我们接触过的Tomcat应该是放置web app的容器,在哪放置web app?这将决定哪个app来处理Engine所获取的请求信息.

再想一下,我们浏览器是个app,对吧?然后服务器其实也是app对吧?网络就是两者的通信.我们来看一下网络是怎么进行通信的.

没错,web app需要端点信息(IP地址,端口号),我们需要提供这一层的抽象.一个Host下可以对应有多个app(Context).

5.现在设计已经可以满足两个应用的连接了,现在设想一下,应用该怎么进行表示?毕竟Tomcat作为一款Servlet容器而存在.首先Apache组织按照Servlet官方的标准,加入了Servlet的包装类Wrapper.

6.就目前为止,我们使用"容器"这一概念来形容处理接收客户端的请求并且返回响应数据的组件,依此,使用一个类Container来统一表示这一想法,让Engine,Host,Context,Wrapper这类组件来继承Container.

Container类能够添加子组件addChild方法,有时需要执行一些异步处理,所以加入backgroundProcess方法.

由于Engine,Host,Context,Wrapper这类的引用变成了父类Container,所以之前的强组合关系变成了弱组合关系.强弱关系指的是两个类直接关联或者是间接关联.

7.为了从抽象和复用层面上再审视一下当前设计,使概念更加清晰,提供通用性定义.由于所有容器都有着自身的生命周期管理方法,那么我们可以将其进行抽象成一个接口Lifecycle,在方法定义上加入初始化方法init,销毁方法destroy,事件监听方法addLifecycleListener和removeLifecycleListener.

8.上面这个设计Container部分具有伸缩性和扩展性,这很棒.接下来Tomcat的开发人员为了提高每个组件的灵活性,使其更易扩展,加入了Pipeline和Valve这两个接口.这两个接口的设计运用了职责链模式.

简单介绍以下职责链模式,关于设计模式可以查看博客里的文章《软件设计 : 聚焦设计模式》

职责链模式使用一个抽象类来统一定义处理器,然后将处理器构造成一条链,当Client端发来请求时,第一个Handler判断是否处理,不处理则往下个Handler传递,直至被处理或则处理链结束.

回头看Tomcat怎么运用这个设计模式,Pipeline接口用于构建职责链,Valve接口代表职责链上的每个处理器.

Pipeline中维护一个基础的Valve,它始终位于Pipeline执行链的末端,封装了具体的请求处理和输出响应过程.

这样就可以构造一条职责链,可是为什么要这么做?记得之前Container不就是可以自包含的容器吗?为什么要弄出多两个接口?

的确,Container可以自包含,但是它是作为容器抽象类而存在,而阀(Valve)作为接口而存在,我们可以在实现这个接口的类中添加属于我们自己的Valve实现类,你想做什么都行.

  就像水管一样,你如果是超级马里奥,你可以随时给它加个阀,做任何事.

9.前面的设计基本落在Container部分,来看看Connector的设计方案,Connector必须完成下面的功能项.

  ①监听服务器端口,读取客户端的请求

  ②将请求数据按指定协议进行解析

  ③根据请求地址匹配正确的容器进行处理

  ④将请求返回客户端

Tomcat支持多协议(HTTP/AJP)和多种IO方式(BIO,NIO,NIO2,APR,HTTP/2)

  

ProtocolHandler表示协议处理器,针对不同的协议和IO方式,提供不同的实现,ProtocolHandler包含一个Endpoint用来启动socket监听,该接口按照IO方式进行分类实现,还包含一个Process用于按照指定协议读取数据,并交由容器处理.

处理逻辑如下:

1.在Connector启动时,Endpoint会启动线程来监听服务器端口,并在接收到请求后调用Process进行数据读取.

2.当Process读取客户端请求之后,需要按照地址映射到具体的容器进行处理,即请求映射.

3.由于Tomcat各个组件采用通用的生命周期进行管理,而且通过管理工具进行状态变更,因此请求映射除了考虑映射规则的实现外,还要考虑容器组件的注册和销毁.

Tomcat采用Mapper来维护容器映射信息,按照映射规则(Servlet规范定义)查找容器;

MapperListener实现LifecycleListener和ContainerListener,用于在容器组件状态变更时,注册或者取消对应的容器映射信息;

MapperListener实现了Lifecycle接口,当Service启动时,会自动作为监听器注册到各个容器组件之上,同时将已创建的容器注册到Mapper;

Tomcat通过适配器模式实现了Connector与Mapper,Container的解耦,默认实现为CoyotoAdapter;

10.到这里,服务器可以正常接入请求和完成响应,可是我们还没考虑到一个关键的问题——并发

Tomcat使用组件式的设计理念,那么也会有并发组件.

Tomcat组织为此提供了一个Executor接口表示一个可以在组件间共享的线程池,该接口同样继承自Lifecycle接口,按照通用组件进行管理.

Executor由Service进行维护,因此同一个Service中的组件共享一个线程池.值得注意的是如果没有定义线程池,相关组件会自动创建线程池,此时线程池不再共享.

在Tomcat中,Endpoint会启动一组线程来监听Socket端口,当接收到客户请求会创建请求处理对象,并交由线程池处理,由此支持并发处理客户端请求.

11.现在Tomcat基础的核心组件已经完整了,但是架构其实还有很多组件没有显示出来.Tomcat开发人员为了让使用者很好地使用Tomcat,提供了一套配置环境来支持系统的可配置性——Catalina.

Catalina代表了整个Servlet容器架构,包含了上面所有组件,还有还没谈及的安全,会话,集群,部署,管理等Servlet容器组件.它通过松耦合的方式集成了Coyoto,以完成按照请求协议进行数据读写.同时,还包括启动入口、Shell程序等.

Bootstrap是Catalina的启动入口.

为什么Tomcat不通过Catalina启动,而又提供了Bootstrap?

查看一下Tomcat发布包目录,Bootstrap并不存放于Catalina的lib目录下,而是置于bin目录中.Bootstrap通过反射调用Catalina实例,与Tomcat服务器完全松耦合,它可以直接依赖JRE运行并为Tomcat应用服务器创建共享类加载器,用于构建Catalina实例以及整个Tomcat服务器.

至此,Tomcat的基础核心组件介绍结束,我们回顾一下组件的概念

Server   表示整个Servlet容器,一个Tomcat运行环境只存在一个Server,可存在多个Service.

Service    表示链接器和处理器的集合,同一个Service下的链接器将请求传至该Service下的处理器

Connector 表示链接器,用于监听并转化Socket请求,支持不同协议与IO方式

Container  表示容器组件,能执行客户端请求并返回响应的组件

Engine    表示顶级容器,是获取目标容器的入口

Host   表示Servlet引擎中的虚拟机,提供Host之类的域名信息

Context  表示一个web app应用上下文环境

Wrapper 具体的Servlet包装类

Executor   组件间共享的线程池

Tomcat启动与请求响应

Tomcat类加载器

应用服务器通常会自行创建类加载器以实现更加灵活的控制,这是对规范的实现(Servlet规范要求每个Web应用都有独立的类加载器实例),也是架构层面的考虑.

书中p46对类加载器进行了详细说明

JVM默认提供了三个类加载器来进行类加载,Tomcat在加载器上进行扩展,用来加载应用自身的类.

Bootstrap  JVM提供,加载JVM运行的基础运行类,即位于%JAVA_HOME%/jre/lib目录下的核心类库

Extension    JVM提供,加载%JAVA_HOME%/jre/lib/ext目录下的扩展类库

System      JVM提供,加载CLASSPATH指定目录下或者-classpath运行参数指定的jar包

         Tomcat的Bootstrap类即由这个加载器载入

Common   以System为父类加载器,是Tomcat应用服务器顶层的公用类加载器,

         其路径common.loader,默认指向$Catalina_Home/lib目录.

Catalina     用于加载Tomcat应用服务器的类加载器,路径为server.loader,

         默认为空,此时Tomcat使用Common类加载器加载应用服务器.

Shared    所有Web应用的类加载器,路径为shared.loader,默认为空.

         此时使用Common类加载器作为Web应用的父加载器.

Web App   加载WEB-INF/classes目录下未压缩的Class和资源文件以及/WEB-INF/lib目录下的jar包.

        该类加载器对当前web应用可见,对其他web应用不可见.

时间: 2024-07-31 14:36:18

服务器 : Apache Tomcat - 理解架构层次的相关文章

Web应用和Web服务器(Apache Tomcat)基本概念

Web服务器 Web应用提供用户通过网络访问资源(静态资源:html等/动态资源:jsp,jar)的服务.为了使用户能够访问到资源,程序开发者不仅需要开发资源文件,还需要开发Web服务器提供给用户访问资源的渠道.随着Web应用的流行,涌现出越来越多优秀的Web服务器,来帮助程序开发者减少工作量,使得程序开发者只专注于资源的提供.目前主流的Web服务器有Weblogic,Tomcat,WebSphere. 首先看一个没有Web服务器的资源如何能被用户访问: Tomcat和目录介绍 Tomcat本质

(tengine+keepalived)+(apache+tomcat)+memcached+mysql实现高可用、负载均衡、可扩展架构

目录 1.高可用.负载均衡.可扩展架构的需要背景 2.系统架构 3.系统规划及说明 4.系统部署及测试 5.总结 1.高可用.负载均衡.可扩展架构的需要背景 从互联网诞生以来,网站架构随着互联网的快速发展发生着巨大的变化,现今,数据每天都在以爆炸式的增长,大数据.云计算等概念被业内炒得沸沸扬扬,这些前沿技术也在各行各业落地开花.每一种新技术的提出几乎都会或多或少影响着IT的基础架构,面对数据的快速增长.我们急需一套高可用.负载均衡.可扩展的架构来作为支撑. 2.系统架构 此次博文介绍一套高可用.

Windows下Apache+Tomcat+jsp+php的服务器整合配置经验总结

对于Apache+Tomcat+jsp+php的整合,针对不同的Tomcat和apache的版本,稍微有些区别. 一.所需软件 (1)JDK: jdk-7u15-windows-x64.exejdk的版本关系倒不是很大,不影响Apache和Tomcat的整合,配置环境变量时注意一些就行了. (2)Apache:httpd-2.2.25-win32-x86-no_ssl.msi apache版本对整合影响不是太大,需要注意的是整合Tomcat时加载模块(modules)时 mod_jk.so 文件

Linux下Apache+tomcat搭建负载均衡服务器集群

之前在我的博客里面写了一篇文章http://blog.csdn.net/yannanying/article/details/43018175,本文就是为了补充当时的那篇文章而写.我记得当时是参考百度经验里面的一篇文章写的,文章地址为http://jingyan.baidu.com/article/ab0b5630b632dbc15afa7dc4.html,寒假的时候按照这篇文章的相关内容搭建了Apache+tomcat服务器集群,当时是弄成功了,回到学校后再次想尝试一下怎么搭建,但是发现自己记

Tomcat 系统架构与设计模式,第 1 部分: 工作原理

Tomcat 系统架构与设计模式,第 1 部分: 工作原理 这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tomcat 如何分发请求.如何处理多用户同时请求,还有它的多级容器是如何协调工作的角度来分析 Tomcat 的工作原理,这也是一个 Web 服务器首要解决的关键问题. 这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tom

【Tomcat】Tomcat 系统架构与设计模式,第 1 部分: 工作原理

这个分为两个部分的系列文章将研究 Apache Tomcat 的系统架构以及其运用的很多经典设计模式.本文是第 1 部分,将主要从 Tomcat 如何分发请求.如何处理多用户同时请求,还有它的多级容器是如何协调工作的角度来分析 Tomcat 的工作原理,这也是一个 Web 服务器首要解决的关键问题. 本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4.Tomcat 的基本设计思路和架构是具有一定连续性的. Tomcat 总体结构 Tomcat 的结构很复杂,但

粗浅看 Tomcat系统架构分析

Tomcat的结构很复杂,但是Tomcat也非常的模块化,找到了Tomcat最核心的模块,就抓住了Tomcat的"七寸". 整体结构 Tomcat 总体结构图 从上图中可以看出Tomcat的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍.Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个Container 可以选择对应多个Con

Tomcat系统架构

Tomcat 系统架构与设计模式,第 1 部分 工作原理 系列内容: 此内容是该系列 2 部分中的第 1 部分: Tomcat 系统架构与设计模式 本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4.Tomcat 的基本设计思路和架构是具有一定连续性的. Tomcat 总体结构 Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的"七寸".下面是 Tomcat 的总体结构图:

基于jersey和Apache Tomcat构建Restful Web服务(一)

基于jersey和Apache Tomcat构建Restful Web服务(一) 现如今,RESTful架构已然成为了最流行的一种互联网软件架构,它结构清晰.符合标准.易于理解.扩展方便,所以得到越来越多网站的采用.那么问题来了,它是什么呢? 起源 REST(Representational state transfer)在 2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一. REST 中最重要的概念是资源(resources