其实讲真的,学习了这么长时间的Web开发,还真的没去想过tomcat到底在 接收到客户端请求的时候到底干了啥。
之前初学的时候也没太将 tomcat 当回事,也只是简单的清楚tomcat作为一个服务器不断的接收用户的请求,接收一个请求开辟一个新的线程,然后发给servlet去处理。
不过最近刚找到工作,闲来无事就看了一下扩展视频。里边有讲到一些tomcat 的请求流程,这里简单记录一下,给自己提个醒。
关于 TCP 和 Socket
首先,我们需要对 Socket 有一定的理解。
学过计网的同学一定知道 TCP 协议。大家都知道,TCP是传输层的协议,它的最主要的功能就是确认数据的可靠传输,那么问题来了?
TCP协议到底是谁实现的?你之前有探索过吗?我其实也是现在才知道,TCP协议原来是由操作系统实现的。当然它也可以在应用App上实现,但是既然大家都用TCP/IP 协议,那么由操作系统来实现,好像更为便利哈哈。
win代码是闭源的,咱也不知道,不过对于linux 来讲,TCP协议由 c语言代码编写,对于创建连接,关闭连接,还有TCP三次握手,四次挥手的流程,这些现在都有操作系统实现了。
但是仔细想一想,我们的应用程序是直接调用 这些代码的具体方法吗?
并不是的,有过开发经验的我们也清楚,一些业务逻辑之类的代码,我们一般都要有一些API接口进行封装。
而对于操作系统而言,这个接口就是 Socket,我们通过Socket 发送和接收数据。
而在 Java 中,我们对外部通信也必须 创建 Socket 对象,不过 Java 本身并不会去创建 TCP连接,因为前边我们也说过,TCP协议的具体实现是操作系统,Socket的源码中会去调用 JVM本地方法,本地方法中回去调用操作系统提供的Socket接口去创建 TCP连接。
对于 HTTP 协议的实现者
HTTP 协议的实现者都有谁呢?我们现在已经知道了,TCP协议由操作系统实现了。那么HTTP呢?
毫无疑问,我们平时使用的浏览器,必然是实现了 HTTP协议的。
那么开发的时候谁去接收请求了?对,就是像Tomcat 这类的服务器。
所以,浏览器负责 HTTP的发送,Tomcat负责HTTP的接收。
他们都必须实现HTTP协议,只不过浏览器更多的偏向于HTTP的发送实现,Tomcat更多的偏向于 HTTP 的接收功能实现。
浏览器也会去调用 操作系统提供的 Sokcet接口去创建 TCP连接,然后发送数据到 Socket。
而 Tomcat 会从 Sokect 去接收数据。
Tomcat 去 Socket 取数据的过程,就会涉及到 IO模型。
所以就会有如下的结构:
Tomcat
IO模型(按照不同的 IO模型去数据,比如说我们常用的 BIO,NIO这两种 io模型)
Sokcet
在Tomcat7,源码中开始有 NIO 和 BIO这两种模型的代码实现,默认采用 BIO
不过后来从 Tomcat8开始中,已经默认采取NIO了。
Tomcat的请求处理流程
Tomcat的请求处理流程主要分为两大部分。
一个是接收客户端发送过来的 HTTP请求,将其封装成 Request和 Response 对象
一个是将 Request 和 Response 对象传给 Servlet,然后调用 Service方法(在 service 中会根据不同的请求类型调用 doGet 和 doPost方法)进行业务处理。
简单来讲就是接收请求和处理请求两大模块,正好对应Tomcat中的两大组件,Connector和 Container。
接收请求
Connector 在某个端口监听请求,只要是来了一个用户请求,Tomcat会从 Sokcet从获取一系列的数据,将HTTP协议的请求行,请求头,请求体一系列的数据序列化(parse),然后根据这些 HTTP协议的数据,将其数据封装成一个 Request对象。然后还会创建一个 Response对象。
值得注意的是在代码中,每一个 Sokcet的 处理,都是会去开辟一个线程的。实现 Runable接口的 run方法中,会采取不同的 IO模型,无论是NIO还是 BIO,这些东西都有对应的具体代码实现。
创建好 Request和 Response后,Tomcat会将这两个对象 传给我们的 Container组件。
处理请求
我们都常说,Tomcat是一个 Servlet的容器
那 Container组件(容器)究竟是啥?
首先要知道 Container 有四种,
- Wrapper:代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了。
- Context:它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的
- Host:虚拟主机,对应部署在 Tomcat上的不同 Web应用程序。
- Engine:执行引擎,Engine 容器比较简单,它只定义了一些基本的关联关系。负责将URL发送到对应的 HOST,也就是说它用来管理Host
而至于 Servlet呢?它只是 JavaEE的一个规范,我们在 Java程序中只需要继承 HttpServlet就行。至于Servlet如何执行。
我们将项目打成 war包部署在 Tomcat中, Tomcat会来装载我们的 Servlet,不过在装载Servlet之前,Tomcat也会去创建一个 FIlterChain(过滤链)。当我们访问这个Servlet的时候,会先去走一遍这个 FilterChain。
总的来讲就是 Tomcat(Servlet容器)来将 封装好的 Request,Response传给 Servlet然后调用 Service的方法来执行。