新手村
上个世纪80年代末,有一天,Tim Berners-Lee正在工作,他需要与另一台计算机上的同事共享一个文件。他尝试使用电子邮件,但发现电子邮件不能发送二进制文件。Tim Berners-Lee意识到,他需要一种新的协议来共享二进制文件。
这是HTTP的第一个版本,甚至于没有版本号,它非常简单,只支持GET请求,但足以方便科学家们可以在不同的计算机之间共享研究数据和文档。
1.0时代
早期的HTTP仅支持文本,随着图片、音视频等流媒体的普及,人们对HTTP的要求也随之增加,这就有了HTTP1.0:增加了 HEAD、POST 等新方法、响应状态码,请求头和响应头等。
常见的状态码:
- 1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。如101表示协议升级。
- 2xx 类状态码表示服务器成功处理了客户端的请求。如200表示成功响应请求。
- 3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源。如301表示永久重定向,302表示临时重定向。
- 4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。如404表示资源不存在。
- 5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。如502表示服务器网关返回错误。
常见字段:
- Content-Length:表示消息体的字节数。
- Accept: 客户端发送请求表明自己支持接收什么样的数据格式。如Accept: */*为接收所有格式
- Content-Type:指示发送端发送的数据是什么样的数据格式。如Content-Type: text/html; Charset=utf-8 表示数据内容为utf-8编码的html文本格式。
- Content-Encoding:说明数据的压缩方法,表示服务器返回数据是什么压缩格式。如Content-Encoding: gzip
1.1时代
由于早期HTTP的特性,每次请求资源都要发起一个新的连接,所以存在很大的性能问题,为此,HTTP从1.0修炼到了1.1。
- 支持长连接:新增Connection字段:,允许客户端或服务端告知对端,将连接持久化,如Connection: Keep-Alive,直到一端主动关闭:Connection: Close
- 支持一台主机上部署多个服务器,新增Host字段:客户端发送请求时,用来指定服务器的域名。如Host: www.baidu.com,用以确定客户端访问的数哪个主机。
- 支持客户端同时发送多个请求,而不必等待前一个请求的响应回来才能发送第二个。
- 支持响应数据分块,响应数据可分多次传输,从而客户端可以优先处理先收到的这部分数据,而不必等待所有数据完成传输。
2.0时代
由于HTTP1.1头部字段越来越多,开销越来越大,服务器响应顺序依赖客户端请求顺序,且服务端仅支持被动响应,优化随之而来。
- 头部压缩:对于常用的协议头,在客户端和服务器分别缓存相同的映射表,头部只携带对应的映射id
- 二进制协议:不再使用文本协议,转为二进制编码,进一步减少占用
- 并发传输:多个stream复用一条tcp连接,支持同时传输多个请求,每个stream传输不同的请求,服务端可并发的响应而不受请求顺序的限制。
- 服务器可主动建立stream实现主动推送数据给客户端。
3.0时代
HTTP2.0看似有多个stream复用一条tcp连接,解决了HTTP队头阻塞的问题,实际仍然存在tcp层的队头阻塞问题。归根结底是2.0是基于tcp协议来传输数据的,而TCP 是字节流协议,上层应用读取tcp内核缓冲区数据必定是连续的,那么当前1个字节没有到达时,后收到的字节数据无法读取到。为了彻底解决这个问题,QUCI来了。
3.0基于QUIC协议实现,其有如下特点:
- 无队头阻塞:类似2.0的多个stream复用一条连接,只不过QUIC基于UDP,所以不存在队头阻塞
- 连接建立更快:可靠连接握手与tls安全握手合二为一,三次握手即建立安全的可靠连接
- 连接迁移:使用连接 ID 来标识通信的两个端点,若移动端网络发生变更,如从wifi切为4G,仍持有连接ID、会话密钥等上下文,避免重新协商新连接。
缺点:由于各大运营商的转发策略限制,大部分带宽不够的场景下,优先丢弃UDP报文,导致QUIC报文有更大的概率被丢弃。
现网多数采用的仍然是1.1或2.0,3.0还尚未普及。