本文原创:fanmengyuan
HTTP 是基于 TCP/IP 协议的一个应用层协议,是现代互联网的一个基础协议。规定了客户端与服务端之间的通信格式以及所占用的服务端口80(HTTPS是443)。
版本
HTTP 协议从开始立项到现在一共经历了 4
个版本:
HTTP 0.9 -> HTTP 1.0 -> HTTP 1.1 -> HTTP 2
HTTP 0.9
HTTP 0.9 是一个最古老的版本
- 只支持
GET
请求方式:由于不支持其他请求方式,因此客户端是没办法向服务端传输太多的信息 - 没有请求头概念:所以不能在请求中指定版本号,服务端也只具有返回 HTML字符串的能力
- 服务端相响应之后,立即关闭TCP连接
HTTP 1.0
随着 HTTP 1.0 的发布,这个版本:
- 请求方式新增了POST,DELETE,PUT,HEADER等方式
- 增添了请求头和响应头的概念,在通信中指定了 HTTP 协议版本号,以及其他的一些元信息 (比如: 状态码、权限、缓存、内容编码)
- 扩充了传输内容格式,图片、音视频资源、二进制等都可以进行传输
在这个版本主要的就是对请求和响应的元信息进行了扩展,客户端和服务端有更多的获取当前请求的所有信息,进而更好更快的处理请求相关内容。
请求头
一个简单请求的头信息
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
可以看到在请求方法之后有 请求资源的位置 + 请求协议版本,之后是一些客户端的信息配置
响应头
一个简单响应的头信息(v1.0)
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
// 这是一个空行
...数据内容
服务端的响应头第一个就是 请求协议版本,后面紧跟着是这次请求的状态码、以及状态码的描述,之后的内容是一些关于返回内容的描述。
Content-Type
在 HTTP 1.0 的时候,任何的资源都可以被传输,传输的格式呢也是多种多样的,客户端在收到响应体的内容的时候就是根据这个 Content-Type
去进行解析的。所以服务端返回时候必须带着这个字段。
一些常见的 Content-Type
可以参考 对照表。
这些 Content-Type
有一个总称叫做MIME type
。
关于MIME type
,这里想播插一个小插曲:
在 chrome 浏览器中,当跨域请求回来的数据 MIME type 同跨域标签应有的 MIME type 不匹配时,浏览器会启动 CORB 保护数据不被泄漏。被保护的数据有: html、xml、json。(eg: script、img 标签所支持的 MIME type和他们都不一致),所以服务端在返回资源的时候一定要对应返回正确的
Content-Type
,以免浏览器屏蔽返回结果。笔者遇到的问题是在 chrome v76 版本之后,跨域图片资源当请求回来的数据
Content-Type
不是image/*
,图片会被拦截,页面不展示图片。
特性
- 无状态:服务器不跟踪不记录请求过的状态
- 无连接:浏览器每次请求都需要建立tcp连接
无状态
对于无状态的特性可以借助cookie/session机制来做身份认证和状态记录
无连接
无连接导致的性能缺陷有两种:
- 无法复用连接
每次发送请求,都需要进行一次tcp连接(即3次握手4次挥手),使得网络的利用率非常低 - 队头阻塞
HTTP 1.0 规定在前一个请求响应到达之后下一个请求才能发送,如果前一个阻塞,后面的请求也给阻塞的
HTTP 1.1
HTTP 1.1 是在 1.0 发布之后的半年就推出了,完善了 1.0 版本。目前也还有很多的互联网项目基于 HTTP 1.1 在向外提供服务。
特性
- 长连接:新增Connection字段,可以设置keep-alive值保持连接不断开
- 管道化:基于上面长连接的基础,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回
- 缓存处理:新增字段cache-control
- 断点传输
长连接
HTTP 1.1默认保持长连接,数据传输完成保持tcp连接不断开,继续用这个通道传输数据
管道化
基于长连接的基础,我们先看没有管道化请求响应:
tcp没有断开,用的同一个通道
请求1 > 响应1 --> 请求2 > 响应2 --> 请求3 > 响应3
管道化的请求响应:
请求1 --> 请求2 --> 请求3 > 响应1 --> 响应2 --> 响应3
即使服务器先准备好响应2,也是按照请求顺序先返回响应1
虽然管道化,可以一次发送多个请求,但是响应仍是顺序返回,仍然无法解决队头阻塞的问题
缓存处理
当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求。
通过设置字段cache-control来控制缓存。
断点传输
在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率
HTTP 2
特性:
- 二进制分帧
- 多路复用: 在共享TCP链接的基础上同时发送请求和响应
- 头部压缩
- 服务器推送:服务器可以额外的向客户端推送资源,而无需客户端明确的请求
二进制分帧
HTTP 1.x 的解析是基于文本,HTTP 2之后将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,提高传输效率
多路复用
在共享TCP链接的基础上同时发送请求和响应,基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来。
头部压缩
由于 HTTP 是无状态的,每一个请求都需要头部信息标识这次请求相关信息,所以会造成传输很多重复的信息,当请求数量增大的时候,消耗的资源就会慢慢积累上去。所以 HTTP 2 可以维护一个头部信息字典,差量进行更新头信息,减少头部信息传输占用的资源,详见 HTTP/2 头部压缩技术介绍。
HTTPS 和 HTTP
- HTTPS 协议需要申请证书
- HTTP 和 HTTPS 使用端口不一样,前者是80,后者是443
- HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,HTTPS 运行在 SSL/TLS 之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的
- HTTPS 可以有效的防止运营商劫持
结尾
虽然在2015年,HTTP 2 就发布了,但是目前互联网的服务中,使用 HTTP 1.x 版本的服务不在少数,其中可能很大的一个原因是在当前的主流浏览器比如 chrome、Firefox 它们只支持基于 TLS 部署的 HTTP 2 协议,也就是说需要你的网站先升级为 HTTPS 才可以。然而 HTTPS 是需要申请证书的。
当然如果你的网站已经升级过 HTTPS 了,那么想升级 HTTP 2 就非常容易了。前端服务利器nginx
能帮你做这所有,详见 Open Source NGINX 1.9.5 Released with HTTP/2 Support