作为一枚java程序员,tomcat绝对是常接触的web服务器,本人对tomcat源码也垂涎已久。近日,终于在工作之余有了些许闲暇时间,学习之,我试图记录学习的过程及结果,一来加深自己的学习印象,二来也分享我的学习过程,或许可以帮助一些同志们少走弯路。废话到此结束,开始正题。
1、源码工程搭建
源码准备准备学习tomncat源码第一步当然是下载tomcat源码,我下载的是最新的tomcat9的源码(附上下载链接http://mirrors.shu.edu.cn/apache/tomcat/tomcat-9/v9.0.6/src/apache-tomcat-9.0.6-src.zip)下载完成后,把源码解压出来。然后在工程目录下创建一个pom.xml文件把它改成maven工程。pom里面内容如下:
4.0.0org.apache.tomcatTomcat9.0Tomcat9.09.0 Tomcat9.0 java test java test org.apache.maven.plugins maven-compiler-plugin 2.3 UTF-8 1.8 1.8 junit junit 4.12 test org.easymock easymock 3.4 ant ant 1.7.0 wsdl4j wsdl4j 1.6.2 javax.xml jaxrpc 1.1 org.eclipse.jdt.core.compiler ecj 4.5.1"
然后在项目根目录下创建lib文件夹并把从网上下载编译好的tomcat项目lib下jar包复制到该源码lib文件夹下。然后打开idea 导入该tocmat maven项目。导入后项目目录如图:
然后配置启动类如图
配置完成后就可启动tomcat项目。启动完成后在浏览器输入http://localhost:8080/验证下tomcat是否成功启动成功。
2、tomcat9整体系统架构
tomcat源码工程构建成功,原本我以为可以愉快地debug学习了,但是理想是丰满的,现实是骨感的。tomcat由于发展了很多年,现在整个源码工程已经十分庞大,若对tomcat的整体架构没有了解,单单靠着一步一步debug将是十分困难的。若想通过对源码的学习来反推出它的系统架构或设计思想更是难上加难,终于经过我一夜的debug还是对tomcat设计思想和整体架构云里雾里后,我放弃了,开始从网上寻找tomcat整体的设计思想和系统架构,先对tomcat整体有宏观的理解,然后分清主次,不去太多的关注细节,这样才对tomcat源码有了粗浅的认识。一下是我根据网上各位大神和自己对源码的阅读整理的tomcat整体架构的整理。
先来一张有名的tomcat架构图
我们来看看tomcat每个组件的作用是什么
2.1、Server
Server代表整个catalina servlet容器。它的特性代表servlet容器的整体特性。Server可以包含一个或多个service,以及顶级的命名资源集。通常,此接口的实现,还将实现生命周期接口,这样当start()和stop()方法被调用,所有它包含的service也开始或停止。在两者之间,实现必须在端口属性指定的端口号上打开服务器套接字。当连接被接受时,读取第一行,并与指定的关闭命令进行比较。如果命令匹配,则启动服务器关机。注意,按图上各个容器或组件的关系此接口的正确实现应该是一个单例的。
2.2、service
service连接一组或多个Connector和一个Container,他们一起来处理传入的请求。也就是一个service把多个Connector和一个Container组装起来才能对外提供服务,二而service也需要生存的土壤这个土壤就是Server。service的标准实现是StandardService它不仅实现了Service接口还实现了Lifycycle接口说明他的上级容器可以控制它的生命周期。
2.3、Connector
Connector负责把接收到的请求解析出来然后封装成request和response对象然后交给Container处理。目前Connector支持http和ajp协议。
2.4、Container
Container字面是容器的意思。既然是容器里面肯定装有东西,那么它装的是什么呢?它装着Engine、Host、Context和Wrapper这几个容器。他们是Container子类型。Engine(引擎)包含Host和Context,接到请求后仍给相应的Host在相应的Context里处理。Host:就是我们所理解的虚拟主机。Context:就是我们所部属的具体Web应用的上下文,每个请求都在是相应的上下文里处理的。Wrapper:Wrapper是针对每个Servlet的Container,每个Servlet都有相应的Wrapper来管理。
2.5、Component 组件:
需求被传递到了容器里面, 在合适的时候, 会传递给下一个容器处理。而容器里面又盛装着各种各样的组件, 我们可以理解为提供各种各样的增值服务。比如:
manager: 当一个容器里面装了manager组件后,这个容器就支持session管理了, 事实上在tomcat里面的session管理, 就是靠的在context里面装的manager component.
logger: 当一个容器里面装了logger组件后, 这个容器里所发生的事情, 就被该组件记录下来, 我们通常会在logs/ 这个目录下看见catalina_log.time.txt 以及localhost.time.txt和localhost_examples_log.time.txt。 这就是因为我们分别为:engin, host以及context(examples)这三个容器安装了logger组件, 这也是默认安装, 又叫做标配 .
loader: loader这个组件通常只会给我们的context容器使用,loader是用来启动context以及管理这个context的classloader用的。
pipline: pipeline是这样一个东西,使用的责任链模式. 当一个容器决定了要把从上级传递过来的需求交给子容器的时候, 他就把这个需求放进容器的管道(pipeline)里面去。 而需求傻呼呼得在管道里面流动的时候, 就会被管道里面的各个阀门拦截下来。 比如管道里面放了两个阀门。 第一个阀门叫做“access_allow_vavle”, 也就是说需求流过来的时候,它会看这个需求是哪个IP过来的, 如果这个IP已经在黑名单里面了,sure, 杀! 第二个阀门叫做“defaul_access_valve”它会做例行的检查, 如果通过的话,OK, 把需求传递给当前容器的子容器。 就是通过这种方式, 需求就在各个容器里面传递,流动, 最后抵达目的地的了。
valve: 就是上面所说的阀门。
Tomcat里面大概就是这么些东西, 我们可以简单地这么理解tomcat的框架,它是一种自上而下, 容器里又包含子容器的这样一种结构。
好了理解了整体架构我们后面来看看tomcat的更深层的技术。。。。