前端必须知道的HTTP

HTTP和Socket是前端经常遇到网络通信相关概念。

HTTP与TCP

HTTP(HyperText Transfer Protocol)的曝光度很高,网页访问、接口请求、服务调用等许多都是通过HTTP协议传输。在历史上,HTTP的设计初衷并没有考虑到这么多应用场景,当初旨在实现从WWW(万维网)服务器传输超文本内容到浏览器,其应用广泛主要得益于它的设计。HTTP是应用层协议,也是基于TCP传输层协议的一种实现。下图中,与TCP上层的应用程序,可以通过HTTP进行通信。

TCP/IP简易网络模型图示

我们经常说的三次握手,就是建立TCP连接的过程。当我们需要通过HTTP协议传输数据时,需要先建立一个TCP连接,三次握手就像对暗号的过程,首先客户端发一个暗号到服务端请求建立连接(第一次握手),然后服务端做出响应回复客户端一个暗号(第二次),发送暗号的同时,服务端要确保客户端收到了自己的信息,所以客户端必须回复一句“收到了”(第三次)。TCP握手建连是一个典型的传令兵逻辑问题,这里不展开说了,但此处引出一个特性,TCP建连不代表后续通信是可靠的。TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”,而断开意味着释放资源。

回到HTTP,有一个特点是客户端每次发送请求都需要服务器响应,请求结束后会主动释放连接。在HTTP 1.0中,客户端每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。 而在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

HTTP KeepAlive

网上经常有HTTP长连接、短连接的叫法,主要是因为请求结束就会断开这个特性。 而上面提到的HTTP1.0和1.1的区别之一就是TCP建连保持的时间。在HTTP1.1中我们可以通过在服务器和客户端设置header信息,实现对保持时间的配置:

Connection: Keep-Alive
Keep-Alive: timeout=5, max=100

Keep-Alive参数[1]有两个:

timeout:指定了一个空闲TCP连接需要保持打开状态的最小时长(以秒为单位)。
max:在TCP连接关闭之前,在此连接可以发送的请求的最大值。

那么现在,我们可以利用这些设置,获得更长时间的TCP连接,比如在连续请求2个HTTP资源时,当其中一个请求先完成,该请求使用的TCP连接不会立刻中断,那么第二个资源请求可以继续使用该连接保持和服务端的通信。

在实际应用中,一个网页通过HTTP1.1协议加载资源,浏览器在同一时刻在同域(domain)下创建的持久TCP请求数是有限制的,不同浏览器(及版本)的限制不同。比如Chrome是6个。这些规则是浏览器根据自身功能和操作系统限制而采用的策略[2]

network.http.max-persistent-connections-per-server=6

HTTP队首阻塞

利用KeepAlive特性,在客户端(浏览器)并发的同域HTTP请求,会共用一个TCP连接。但是在HTTP1.0/1.1协议下,浏览器会依次等待发出的请求响应,因此当第一个HTTP请求响应在队列中消耗较长的传输时间,处于同一TCP连接中的其他HTTP请求就需要排队等待接收响应。这就叫队首阻塞。

Chrome每个主机最多强制实施6个TCP连接。如果您一次请求12个项目,则前6个开始,后半部分排队。一旦原始一半完成,队列中的第一项将开始其请求过程。

实例

而在HTTP2中(这里简单提一下),不会存在首阻塞的现象[3]

参考引用

[1] MDN – KeepAlive https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Keep-Alive

[2]浏览器TCP限制 https://www.zhihu.com/question/20474326/answer/15691654

[3]HTTP2 https://segmentfault.com/a/1190000006923359

留下评论

电子邮件地址不会被公开。 必填项已用*标注