HTTP的特征
HTTP
-
简单
-
灵活和易于扩展
HTTP在应用层,他的下层可以随意变化,比如:HTTPS就是在HTTP和TCP之间加上SSL/TLS安全传输层,HTTP/3把下层的TCP换成了基于UDP的QUIC。
-
应用广泛和跨平台使用
HTTP的缺点:明文传输,无状态,不安全。
对于HTTP无连接无状态。
无连接的意思就是每次连接只处理一个请求,服务器处理完客户端的请求,并收到客户的应答后立即断开连接,也就是处理完一个就关闭连接。
无状态就是客户端和服务器不会有缓存来记录状态信息,因此在完成有关联性的操作时非常麻烦,麻烦在于后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大,每次操作都要验证一下信息。
对于无状态问题,解决方法主要就是利用cookie技术,通过在请求和响应报文中写入cookie信息来控制客户端的状态。
cookie是怎么工作的?
- 浏览器第一次访问服务器时,服务器此时肯定不知道它的身份,所以创建一个独特的身份标识数据,格式为key=value,放入到Set-Cookie字段里,随着响应报文发给浏览器。
- 浏览器看到有Set-Cookie字段以后就知道这是服务器给的身份标识,于是就保存起来,下次请求时会自动将此key=value值放入到Cookie字段中发给服务器。
- 服务器收到请求报文后,发现Cooke字段中有值,就能根据此值识别用户的身份然后提供个性化的服务。
有了Cookie实现了有状态这一需求,那为什么又来一个Session呢?
试想一下,如果将用户账户的一些信息都存入Cookie中的话,一旦信息被拦截,那么所有的账户信息都会可能被泄露丢,这是不安全的。所以就出现了Session,在一次会话中将重要信息保存在Session中,浏览器只记录Sessionld一个Sessionld对应一次会话请求。
cookie和session的区别:
①Cookie可以存储在浏览器或者本地,Session只能存在服务器
②session 能够存储任意的对象类型,cookie 只能存储 String 类型的对象
③Session比Cookie更具有安全性(Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击)
④Session占用服务器性能,Session过多,增加服务器压力
⑤单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie,Session是没有大小限制和服务器的内存大小有关。
HTTP/1.1
- 长连接
问题:在早期HTTP/1.0就是每次发起一个请求,都要新建一次TCP三次握手的连接,而且是串行请求,这样做了很多无谓的TCP连接建立和断开,增加了通信开销。
解决:在HTTP/1.1中提出了**长连接(keep-alive)**的通信方式。减少了TCP重新连接带来的通信开销。持久连接的特点是:只要任意一端没有明确的提出断开连接,则保持TCP连接状态。
- 管道网络传输
由于HTTP/1.1采用了长连接,因此这使得管道网络传输成为可能。
在同一个TCP连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不用等其回来,就可以发送第二个请求出去,可以减少整体的响应时间。
但是服务器还是按照顺序,先回应前面一个请求A,再回应后面的请求B,如果前面的回应特别慢,后面的许多请求也要排队等着,这就是队头阻塞。
HTTP/2.0
HTTP/2相比于HTTP/1.1又做了一些改进:
-
HTTP/2协议是基于HTTPS的,所以HTTP/2的安全性是有保障的。
-
头部压缩
HTTP/1.1只压缩了
body
部分,未压缩头部(Header)。HTTP/2会压缩头,如果你同时发出多个请求,他们的头是一样的或者相似的,那么HTTP/2会帮你消除重复的部分。在客户端和服务器同时维护一张头部信息表,所有字段都会存入这个表,生成一个索引号,以后就只发送索引号就行了,提高了速度。 -
二进制格式
HTTP/1.1是以纯文本形式的报文,在HTTP/2采用了二进制格式,header和body都是二进制,统称为帧(头信息帧和数据帧)。这样在接收端无需再将明文的报文转成二进制,而是直接解析二进制报文,这样增加了数据传输的效率。
也即:HTTP 2.0 将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。
常见的帧有Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。
-
数据流
HTTP/2不是按序发送的,同一个连接中连续的数据包,可能属于不同的回应,因此必须要对数据包进行标记,指出属于哪个回应。每个请求和响应的所有数据包称为一个流。每个数据流都标记着一个编号。还能自行指定流的优先级。
-
多路复用
HTTP/2是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。避免了队头阻塞,降低了延时,大幅度提高了连接的利用率。
-
服务器推送
HTTP 1.1 存在的问题:HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 的头,而且不考虑 pipeline 模式的话,每次的过程总是像上面描述的那样一去一回。这样在实时性、并发性上都存在问题。
HTTP 2.0优点通过头压缩、分帧、二进制编码、多路复用等技术提升性能。
通过分帧,二进制编码和多路复用这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送,然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。
例如:一个页面要发送三个独立的请求,一个获取 css,一个获取 js,一个获取图片 jpg。
如果使用 HTTP 1.1 就是串行的,但是如果使用 HTTP 2.0,就可以在一个连接里,客户端和服务端都可以同时发送多个请求或回应,而且不用按照顺序一对一对应。
HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题(串行发送),减少了 TCP 连接数对服务器性能的影响,加快页面组件的传输速度。
HTTP 2.0 虽然大大增加了并发性,但还是有问题的。因为 HTTP 2.0 也是基于 TCP 协议的,TCP 协议在处理包时是有严格顺序的。
当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行。
也就是说虽然在应用层是多路复用的增强了并发性,但是在传输层还依然由TCP的特性(需要接收到确认号才继续发)限制了传输效率。
因此很容易想到可以利用UDP来改善一下这个问题。
具体就是采用QUIC协议。
QUIC协议
QUIC(Quick UDP Internet Connections)是Google设计的一套可靠UDP传输协议,旨在为HTTP提供一个安全、可靠、高效和低延时的通信基础。
QUIC 协议通过基于 UDP 自定义的类似 TCP 的连接、重试、多路复用、流量控制技术,进一步提升性能。
它有以下机制:
(1)自定义连接机制
我们都知道,一条 TCP 连接是由四元组标识的,分别是源 IP、源端口、目的 IP、目的端口。一旦一个元素发生变化时,就需要断开重连,重新连接。每次重连都会进行三次握手,导致一定的时延。
但是对于 UDP,就可以在 QUIC 自己的逻辑里面维护连接的机制,不再以四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。
(2)自定义重传机制
TCP 为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题。一旦超时就需要重传,在判断超时的时候采用RTT(往返时间)来计算,从而有了自适应重传算法。
也就是说TCP 里面超时的采样存在不准确的问题。
例如发送一个包,序号为 100,发现没有返回,于是再发送一个 100,过一阵返回一个 ACK101。RTT计算不知道用前一个100的发送时间还是后一个。
QUIC 也有个序列号,是递增的。任何一个序列号的包只发送一次,下次就要加一了。
例如,发送一个包,序号是 100,发现没有返回;再次发送的时候,序号就是 101 了;如果返回的 ACK 100,就是对第一个包的响应。如果返回 ACK 101 就是对第二个包的响应,RTT 计算相对准确。
(3)无阻塞的多路复用
有了自定义的连接和重传机制,我们就可以解决上面 HTTP 2.0 的多路复用问题。
同 HTTP 2.0 一样,同一条 QUIC 连接上可以创建多个 stream,来发送多个 HTTP 请求。但是,QUIC 是基于 UDP 的,丢了一个 UDP 包,后面的包不需要等待前一个包重传,就能直接发送。(它重传它的,我发送我的)
(4)自定义流量控制
TCP 的流量控制是通过滑动窗口协议。QUIC 的流量控制也是通过 window_update,来告诉对端它可以接受的字节数。
TCP协议是根据累计应答的方式来回传ACK的,前面某个包没到,后面的包即便到了也不能发送ACK。
QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发。
QUIC的窗口的起始位置为当前收到的最大 offset(偏移量),从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。
HTTPS协议
HTTP和HTTPS的区别:
- HTTP是超文本传输协议,明文传输不安全。而HTTPS是为了解决HTTP的安全性,在HTTP和TCP层之间加入SSL/TLS安全协议,使得报文能够加密传输。
- HTTP传输比较简单,TCP三次握手后就能进行HTTP的报文传输,而HTTPS在TCP三次握手后还要进行SSL/TLS的握手过程,才可进入加密报文传输。
- HTTP的端口号是80,HTTPS的端口号443.
- HTTPS协议需要向CA申请数字证书,保证服务器的身份是可信的。
加密方式
HTTPS采用的是对称加密和非对称加密结合的「混合加密」方式:
(非对称加密:公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。)
-
在通信建立之前采用非对称加密的方式交换会话秘钥,后续就不再使用非对称加密。
-
在通信过程中全部使用对称加密的会话秘钥的方式加密明文数据。
对称加密算法相比非对称加密算法来说,效率要高得多,性能也好。
为了保证公钥的信任度和不被篡改,需要借助第三方权威机构CA,将服务器公钥放在数字证书中,只要证书是可信的,公钥就是可信的。
TLS四次握手
SSL/TLS协议基本流程:SSL/TLS的「握手阶段」涉及四次通信。
-
ClientHello
首先客户端向服务器发起加密通信请求,也就是ClientHello请求。(明文)
客户端主要向服务器发送以下信息:(1)客户端支持的SSL/TLS协议版本,支持的密码套件列表。(2)一个随机数,用于后面生产会话秘钥。
-
ServerHello
服务器收到客户端请求后,向客户端发出响应,服务器回应内容如下:
(1)确认TLS协议版本和密码套件列表。(2)服务器生产随机数,用于后面生产会话秘钥。(3)服务器的数字证书。
-
客户端回应
客户端收到服务器的回应之后,通过浏览器或者操作系统中的CA公钥,确认服务器的数字证书的真实性。客户端从数字证书中取出服务器公钥,然后使用它加密报文,向服务器发送如下信息:
(1)一个随机数(pre-master key),该随机数会被服务器公钥加密。(2)加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信。(3)客户端握手通知,表示客户端的握手阶段结束,并且同时会把之前所有内容发生的数据做个摘要,用来服务端校验。
-
服务器的最后回应
服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次的会话秘钥,然后向客户端发送最后的消息:
(1)加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信。(2)服务器握手结束,并且同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。
HTTPS 是综合了对称加密和非对称加密算法的 HTTP 协议。既保证传输安全,也保证传输效率。
参考:极客时间《趣谈网络协议》, 小林coding.