一、基础概念
1.Web容器是什么?
让我们先来简单回顾一下Web技术的发展历史,可以帮助你理解Web容器的由来。
早期的Web应用主要用于浏览新闻等静态页面,HTTP服务器(比如Apache、Nginx)向浏览器返回静态HTML,浏览器负责解析HTML,将结果呈现给用户。
随着互联网的发展,我们已经不满足于仅仅浏览静态页面,还希望通过一些交互操作,来获取动态结果,因此也就需要一些扩展机制能够让HTTP服务器调用服务端程序。
于是Sun公司推出了Servlet技术。你可以把Servlet简单理解为运行在服务端的Java小程序,但是Servlet没有main方法,不能独立运行,因此必须把它部署到Servlet容器中,由容器来实例化并调用Servlet。
而Tomcat和Jetty就是一个Servlet容器。为了方便使用,它们也具有HTTP服务器的功能,因此Tomcat或者Jetty就是一个“HTTP服务器 + Servlet容器”,我们也叫它们Web容器。
其他应用服务器比如JBoss和WebLogic,它们不仅仅有Servlet容器的功能,也包含EJB容器,是完整的Java EE应用服务器。从这个角度看,Tomcat和Jetty算是一个轻量级的应用服务器。
在微服务架构日渐流行的今天,开发人员更喜欢稳定的、轻量级的应用服务器,并且应用程序用内嵌的方式来运行Servlet容器也逐渐流行起来。之所以选择轻量级,是因为在微服务架构下,我们把一个大而全的单体应用,拆分成一个个功能单一的微服务,在这个过程中,服务的数量必然要增加,但为了减少资源的消耗,并且降低部署的成本,我们希望运行服务的Web容器也是轻量级的,Web容器本身应该消耗较少的内存和CPU资源,并且由应用本身来启动一个嵌入式的Web容器,而不是通过Web容器来部署和启动应用,这样可以降低应用部署的复杂度。
因此轻量级的Tomcat和Jetty就是一个很好的选择,并且Tomcat它本身也是Spring Boot默认的嵌入式Servlet容器。最新版本Tomcat和Jetty都支持Servlet 4.0规范。
二、HTTP协议
这里主要介绍和web容器交互所关联的内容
1.HTTP请求流程
请你来看下面这张图,我们过一遍一次HTTP的请求过程。
从图上你可以看到,这个过程是:
1.用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览器获取了这个事件。
2.浏览器向服务端发出TCP连接请求。
3.服务程序接受浏览器的连接请求,并经过TCP三次握手建立连接。
4.浏览器将请求数据打包成一个HTTP协议格式的数据包。
5.浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。
6.服务端程序拿到这个数据包后,同样以HTTP协议格式解包,获取到客户端的意图。
7.得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。
8.服务器将响应结果(可能是HTML或者图片等)按照HTTP协议格式打包。
9.服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。
10.浏览器拿到数据包后,以HTTP协议的格式解包,然后解析数据,假设这里的数据是HTML。
11.浏览器将HTML文件展示在页面上。
那我们想要探究的Tomcat和Jetty作为一个HTTP服务器,在这个过程中都做了些什么事情呢?主要是接受连接、解析请求数据、处理请求和发送响应这几个步骤。这里请你注意,可能有成千上万的浏览器同时请求同一个HTTP服务器,因此Tomcat和Jetty为了提高服务的能力和并发度,往往会将自己要做的几个事情并行化,具体来说就是使用多线程的技术。
2.HTTP请求响应实例
你有没有注意到,在浏览器和HTTP服务器之间通信的过程中,首先要将数据打包成HTTP协议的格式,那HTTP协议的数据包具体长什么样呢?这里我以极客时间的登陆请求为例,用户在登陆页面输入用户名和密码,点击登陆后,浏览器发出了这样的HTTP请求:
你可以看到,HTTP请求数据由三部分组成,分别是请求行、请求报头、请求正文。当这个HTTP请求数据到达Tomcat后,Tomcat会把HTTP请求数据字节流解析成一个Request对象,这个Request对象封装了HTTP所有的请求信息。接着Tomcat把这个Request对象交给Web应用去处理,处理完后得到一个Response对象,Tomcat会把这个Response对象转成HTTP格式的响应数据并发送给浏览器。
我们再来看看HTTP响应的格式,HTTP的响应也是由三部分组成,分别是状态行、响应报头、报文主体。同样,我还以极客时间登陆请求的响应为例。
具体的HTTP协议格式,你可以去网上搜索,我就不再赘述了。为了更好地帮助你理解HTTP服务器(比如Tomcat)的工作原理,接下来我想谈一谈Cookie跟Session的原理。