Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。
web服务器按功能分类可分为:
|- Web Server
|- Http Server
|- Application Server
|- Servlet Container
|- CGI Server
|- ......
Http 服务器:
HTTP Server本质上也是一种应用程序——它通常运行在服务器之上,绑定服务器的IP地址并监听某一个tcp端口来接收并处理HTTP请求,这样客户端(一般来说是IE, Firefox,Chrome这样的浏览器)就能够通过HTTP协议来获取服务器上的网页(HTML格式)、文档(PDF格式)、音频(MP4格式)、视频(MOV格式)等等资源。
一个HTTP Server关心的是HTTP协议层面的传输和访问控制,所以在Apache/Nginx上你可以看到代理、负载均衡等功能。
HTTP Server中经常使用的是Apache、Nginx两种,HTTP Server主要用来做静态内容服务、代理服务器、负载均衡等。直面外来请求转发给后面的应用服务(Tomcat,django什么的)。
|- Http Server
|- Apache
|- Nginx
Application 服务器:
Application Server 是一个应用执行的服务器。它首先需要支持开发语言的 Runtime(对于 Tomcat 来说,就是 Java),保证应用能够在应用服务器上正常运行。其次,需要支持应用相关的规范,例如类库、安全方面的特性。与HTTP Server相比,Application Server能够动态的生成资源并返回到客户端。
|- Application Server
|- Tomcat
|- Jetty
应用服务器往往也会集成 HTTP Server 的功能,但是不如专业的 HTTP Server 那么强大,所以Application Server往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容之后,通过 HTTP Server 分发到客户端。
Tomcat运行在JVM之上,它和HTTP服务器一样,绑定IP地址并监听TCP端口,同时还包含以下指责:
1. 管理Servlet程序的生命周期;
2. 将URL映射到指定的Servlet进行处理;
3. 与Servlet程序合作处理HTTP请求——根据HTTP请求生成HttpServletRequest/Response对象并传递给Servlet进行处理,
将Servlet中的HttpServletResponse对象生成的内容返回给浏览器;
Tomcat 属于是一个「Application Server」,但是更准确的来说,是一个「Servlet/JSP」应用的容器。
1.Server(服务器): Server的实现类StandardServer可以包含一个到多个Service。
2.Service(服务): Service的实现类StandardService调用了容器(Container)接口,即Servlet Engine(引擎),并且指明了该
Service归属的Server,它将一个或者多个Connector组件和一个Engine建立关联。
3.Container(容器): Engine(引擎)、Host(主机)、Context(上下文)均继承自Container接口,它们都是容器。
他们有父子关系,Engine是顶级容器,直接包含Host容器,而Host容器又包含Context容器
Engine 在Service组件中有且只有一个;Engine组件从一个或多个Connector中接收请求并处理,
并将完成的响应返回给Connector,最终传递给客户端。
Host 定义了一个虚拟主机,一个虚拟主机可以有多个Context
Context 每一个运行的webapp其实最终都是以Context的形成存在,每个Context都有一个根路径和请求URL路径,
即每个context就对应一个web应用
4.Connector(连接器): Connector(连接器)将 Service(服务)和 Container(容器)连接起来,
首先它需要注册到一个Service,它的作用就是把来自客户端的请求转发到Container(容器),
这就是它为什么称作连接器的原因。
server.xml的整体结构如下:
Tomcat的核心是两个组件:连接器(Connector)和容器(Container)
Connector:负责生成 请求对象 和 响应对象,Tomcat默认的是HttpConnector,
根据收到的Http请求报文生成Request对象和Response对象,并把这两个对象传递给Container,
然后根据Response中的内容生成相应的HTTP报文。
Container:容器的父接口,所有子容器都必须实现这个接口,就是说服务器部署的项目是运行在Container中的。
Container里面的项目获取到Connector传递过来对应的的Request对象和Response对象进行相应的操作。
多个Connector和一个Container就形成了一个Service,有了Service就可以对外提供
Tomcat要为一个Servlet的请求提供服务,需要做四件事:
1. 创建一个request对象 并填充那些有可能被所引用的Servlet使用的信息,如参数,头部、cookies、查询字符串等
一个request对象就是javax.servlet.ServletRequest或javax.servlet.http.ServletRequest接口的一个实例
2. 创建一个response对象,所引用的servlet使用它来给客户端发送响应
一个response对象是javax.servlet.ServletResponse或javax.servlet.http.ServletResponse接口的一个实例
3. 调用servlet的service方法,并传入request和response对象。这里servlet会从request对象取值,给response写值
4. 根据servlet返回的response生成相应的HTTP响应报文
很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动。
这样,这些应用服务器的性能基本上就取决于Tomcat处理HTTP请求的connector模块的性能。
1. Tomcat是运行在JVM中的一个进程。它被定义为-中间件,是一个在 Java 项目与JVM之间的中间容器
2. Web项目没有入口方法(main方法),意味着Web项目中的方法不会自动运行起来
3. Web项目部署进Tomcat的webapp中,就是希望Tomcat去调用写好的方法去为客户端返回需要的资源和数据
4. Tomcat可以运行起来,并调用写好的方法,表明 Tomcat 一定有一个main方法
5. 对于Tomcat而言,它并不知道我们会有什么样的方法,这些都只是在项目被部署进webapp后才确定,
因此,Tomcat必然用到了Java的反射来实现类的动态加载、实例化、获取方法、调用方法。
6. 根据协议和端口号选定Service和Engine
Service中的Connector组件可接收特定端口的请求,Tomcat启动时,Service组件监听特定的端口。
Catalina这个Service监听了8080端口(基于HTTP协议)和8009端口(基于AJP协议)。
请求进来时,Tomcat 根据 协议 和 端口号 选定处理请求的Service;Service一旦选定,Engine也就确定。
7. 根据域名或IP地址选定Host
Service确定后,Tomcat在Service中寻找 名称 与 域名/IP地址 匹配的Host处理该请求。
如果没有找到,则使用Engine中指定的defaultHost来处理该请求。
8. 根据URI选定Context/Web应用
Tomcat根据应用的 path属性与URI的匹配程度来选择Web应用处理相应请求
9.Tomcat如何确定调用什么方法,取决于客户端的请求,比如:http://127.0.0.1:8080/StudentList/index.java?show这样的一个请求,通过http协议 和 8080端口 选定Service;通过主机名(127.0.0.1)选定Host;然后通过uri(/StudentList/index.java?show)选定Web应用
假设来自客户的请求为:http://localhost:8080/test/index.jsp
1. 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
2. Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应
3. Engine获得请求localhost:8080/test/index.jsp,匹配它所有虚拟主机Host
4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5. localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context
6. Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
7. path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet
8. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10.Context把执行完了之后的HttpServletResponse对象返回给Host
11.Host把HttpServletResponse对象返回给Engine
12.Engine把HttpServletResponse对象返回给Connector
13.Connector把HttpServletResponse对象返回给客户browser