You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
9.6 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 02 | HTTP协议必知必会
在开始学习Web容器之前我想先问你一个问题HTTP和HTML有什么区别
为什么我会问这个问题你可以把它当作一个入门测试检测一下自己的对HTTP协议的理解。因为Tomcat和Jetty本身就是一个“HTTP服务器 + Servlet容器”如果你想深入理解Tomcat和Jetty的工作原理我认为理解HTTP协议的工作原理是学习的基础。
如果你对这个问题还稍有迟疑那么请跟我一起来回顾一下HTTP协议吧。
## HTTP的本质
HTTP协议是浏览器与服务器之间的数据传送协议。作为应用层协议HTTP是基于TCP/IP协议来传递数据的HTML文件、图片、查询结果等HTTP协议不涉及数据包Packet传输主要规定了客户端和服务器之间的通信格式。
下面我通过一个例子来告诉你HTTP的本质是什么。
假如浏览器需要从远程HTTP服务器获取一个HTML文本在这个过程中浏览器实际上要做两件事情。
* 与服务器建立Socket连接。
* 生成**请求数据**并通过Socket发送出去。
第一步比较容易理解,浏览器从地址栏获取用户输入的网址和端口,去连接远端的服务器,这样就能通信了。
我们重点来看第二步,这个请求数据到底长什么样呢?都请求些什么内容呢?或者换句话说,浏览器需要告诉服务端什么信息呢?
首先最基本的是你要让服务端知道你的意图你是想获取内容还是提交内容其次你需要告诉服务端你想要哪个内容。那么要把这些信息以一种什么样的格式放到请求里去呢这就是HTTP协议要解决的问题。也就是说**HTTP协议的本质就是一种浏览器与服务器之间约定好的通信格式**。那浏览器与服务器之间具体是怎么工作的呢?
## HTTP工作原理
请你来看下面这张图我们过一遍一次HTTP的请求过程。
![](https://static001.geekbang.org/resource/image/f5/ca/f5bd0c7840160d5a121c191e7e54b4ca.jpg)
从图上你可以看到,这个过程是:
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为了提高服务的能力和并发度往往会将自己要做的几个事情并行化具体来说就是使用多线程的技术。这也是专栏所关注的一个重点我在后面会进行专门讲解。
## HTTP请求响应实例
你有没有注意到在浏览器和HTTP服务器之间通信的过程中首先要将数据打包成HTTP协议的格式那HTTP协议的数据包具体长什么样呢这里我以极客时间的登陆请求为例用户在登陆页面输入用户名和密码点击登陆后浏览器发出了这样的HTTP请求
![](https://static001.geekbang.org/resource/image/f5/14/f58bf57649ec9eb35eb24e0679bb2514.png)
你可以看到HTTP请求数据由三部分组成分别是**请求行、请求报头、请求正文**。当这个HTTP请求数据到达Tomcat后Tomcat会把HTTP请求数据字节流解析成一个Request对象这个Request对象封装了HTTP所有的请求信息。接着Tomcat把这个Request对象交给Web应用去处理处理完后得到一个Response对象Tomcat会把这个Response对象转成HTTP格式的响应数据并发送给浏览器。
我们再来看看HTTP响应的格式HTTP的响应也是由三部分组成分别是**状态行、响应报头、报文主体**。同样,我还以极客时间登陆请求的响应为例。
![](https://static001.geekbang.org/resource/image/84/b7/84f4fe4c411dfb9fd83a1d53cf2915b7.png)
具体的HTTP协议格式你可以去网上搜索我就不再赘述了。为了更好地帮助你理解HTTP服务器比如Tomcat的工作原理接下来我想谈一谈Cookie跟Session的原理。
## Cookie和Session
我们知道HTTP协议有个特点是无状态请求与请求之间是没有关系的。这样会出现一个很尴尬的问题Web应用不知道你是谁。比如你登陆淘宝后在购物车中添加了三件商品刷新一下网页这时系统提示你仍然处于未登录的状态购物车也空了很显然这种情况是不可接受的。因此HTTP协议需要一种技术让请求与请求之间建立起联系并且服务器需要知道这个请求来自哪个用户于是Cookie技术出现了。
**1\. Cookie技术**
Cookie是HTTP报文的一个请求头Web应用可以将用户的标识信息或者其他一些信息用户名等存储在Cookie中。用户经过验证之后每次HTTP请求报文中都包含Cookie这样服务器读取这个Cookie请求头就知道用户是谁了。**Cookie本质上就是一份存储在用户本地的文件里面包含了每次请求中都需要传递的信息**。
**2\. Session技术**
由于Cookie以明文的方式存储在本地而Cookie中往往带有用户信息这样就造成了非常大的安全隐患。而Session的出现解决了这个问题**Session可以理解为服务器端开辟的存储空间里面保存了用户的状态**用户信息以Session的形式存储在服务端。当用户请求到来时服务端可以把用户的请求和用户的Session对应起来。那么Session是怎么和请求对应起来的呢答案是通过Cookie浏览器在Cookie中填充了一个Session ID之类的字段用来标识请求。
具体工作过程是这样的服务器在创建Session的同时会为该Session生成唯一的Session ID当浏览器再次发送请求的时候会将这个Session ID带上服务器接受到请求之后就会依据Session ID找到相应的Session找到Session后就可以在Session中获取或者添加内容了。而这些内容只会保存在服务器中发到客户端的只有Session ID这样相对安全也节省了网络流量因为不需要在Cookie中存储大量用户信息。
**3\. Session创建与存储**
那么Session在何时何地创建呢当然还是在服务器端程序运行的过程中创建的不同语言实现的应用程序有不同的创建Session的方法。在Java中是Web应用程序在调用HttpServletRequest的getSession方法时由Web容器比如Tomcat创建的。那HttpServletRequest又是什么呢别着急我们下一期再聊。
Tomcat的Session管理器提供了多种持久化方案来存储Session通常会采用高性能的存储方式比如Redis并且通过集群部署的方式防止单点故障从而提升高可用。同时Session有过期时间因此Tomcat会开启后台线程定期的轮询如果Session过期了就将Session失效。
## 本期精华
HTTP协议和其他应用层协议一样本质上是一种通信格式。回到文章开头我问你的问题其实答案很简单HTTP是通信的方式HTML才是通信的目的就好比HTTP是信封信封里面的信HTML才是内容但是没有信封信也没办法寄出去。HTTP协议就是浏览器与服务器之间的沟通语言具体交互过程是请求、处理和响应。
由于HTTP是无状态的协议为了识别请求是哪个用户发过来的出现了Cookie和Session技术。Cookie本质上就是一份存储在用户本地的文件里面包含了每次请求中都需要传递的信息Session可以理解为服务器端开辟的存储空间里面保存的信息用于保持状态。作为Web容器Tomcat负责创建和管理Session并提供了多种持久化方案来存储Session。
## 课后思考
在HTTP/1.0时期每次HTTP请求都会创建一个新的TCP连接请求完成后之后这个TCP连接就会被关闭。这种通信模式的效率不高所以在HTTP/1.1中引入了HTTP长连接的概念使用长连接的HTTP协议会在响应头加入Connection:keep-alive。这样当浏览器完成一次请求后浏览器和服务器之间的TCP连接不会关闭再次访问这个服务器上的网页时浏览器会继续使用这一条已经建立的连接也就是说两个请求可能共用一个TCP连接。
今天留给你的思考题是我在上面提到HTTP的特点是无状态的多个请求之间是没有关系的这是不是矛盾了
不知道今天的内容你消化得如何?如果还有疑问,请大胆的在留言区提问,也欢迎你把你的课后思考和心得记录下来,与我和其他同学一起讨论。如果你觉得今天有所收获,欢迎你把它分享给你的朋友。