《HTTP权威指南》笔记:第四章-连接管理

2021-11-15  本文已影响0人  前端艾希

一、TCP连接

世界上几乎所有的HTTP通信都是TCP/IP承载的,TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交换网络分层协议集。

1.1 TCP的可靠数据管道

TCP连接是因特网上的可靠连接,为HTTP提供了一条可靠的比特传输管道,从TCP连接一段填入的字节会从另一端以原有的顺序正确的传送出来。

1.2 TCP流是分段的,由IP分组传送

TCP的数据通过名为IP分组IP数据报)的小数据块来发送的。HTTP要发送一条报文时会以流的形式使用TCP连接传输,TCP接收到数据流之后将其进行截断分组封装到IP分组内。每个IP分组由以下几部分组成:

HTTP模型:HTTP -> TCP -> IP...

HTTPS模型:HTTP -> TLSSSL -> TCP -> IP...

1.3 保持TCP连接的正常运行

TCP连接时通过4哥值来识别的,这四个值一起唯一定义一条连接:

<源IP 源端口 目标IP 目标端口>

这其中任一值不同都不能称为同一个连接。

二、对TCP性能的考虑

HTTP位于TCP上层,以所HTTP事务性能再很大程度上取决于底层TCP通道的性能。

2.1 HTTP事务的时延

一般来说,在整个HTTP事务周期内,服务端对事务的处理所占时间可能是最短的(除非服务端超载或者处理复杂的动态资源),所以大部分时延都是由TCP网络时延构成的。

HTTP事务时延有以下几种原因:

  1. DNS查询,可能最多会花费数十秒时间。
  2. 建立TCP连接,一个TCP连接需要SYN/ACK+SYN三次报文传输才能建立,但是第三次的IP数据报中可以装载HTTP报文了。
  3. 服务器处理事务,连接建立后,服务器接收到客户端的报文,然后开始处理,处理事务也会花费一定时间。
  4. 网络传输,服务端返回结果在网络中传输需要一定时间。

从以上原因可以看出,HTTP时延的大小取决于:硬件速度,网络和服务器负载,报文尺寸,以及端到端的距离,还有TCP协议产生的时延。

2.2 TCP产生时延的总结

2.3 握手时延

众所周知建立TCP连接需要三次握手:

  1. 客户端发送一个TCP分组(40~60字节),分组中设置了SYN标记。
  2. 服务端接收连接之后,对连接参数进行计算,并把TCP分组的SYNACK都置位。
  3. 最后客户端向服务端返回一条确认TCP分组,其中ACK被置位,并且在这个分组中可以添加HTTP报文。

2.4 延迟确认

TCP为了确保可靠传输,实现了确认机制,及每个TCP段都有一个序列号和数据完整性校验和,段的接收者在收到完好的段后会会向发送者回复一个确认TCP分组,如果发送者没有在指定窗口时间内收到确认分组就会认为发送失败并且会重新发送数据。

由于确认分组很小,所以TCP会允许在发往同方向的分组中对其进行捎带,为了增加捎带的可能,TCP实现了一种延迟确认的算法。即将确认信息缓存下来在特定时间窗口内(100 ~ 200ms)如果有可以捎带的TCP分组,那么从缓存中取出来确认信息,然后进行捎带。如果在这个窗口内没有同方向的TCP分组,那么就需要创建一个TCP分组单独传输确认信息。

2.5 TCP慢启动

TCP连接刚建立后,传输速率会被限制,然后随着时间的推移慢慢提高传输速率,主要用于防止网络突然过载。

2.6 Nagle算法

一个IP分组最小都携带了40字节大小的首部,如果被传输的数据很少的话,那么TCP的效率就想当低了,所以Nagle算法鼓励发送全尺寸的段(因特网上一般为几百字节),所以当有TCP段还没有收到确认分组时,也会被缓存起来,和新的数据凑在一起凑够全尺寸再发送出去。Nagle算法和TCP的延迟确认机制存在一定的冲突。。。所以大部分HTTP应用会设置TCP_NODELAY来禁用Nagle算法。

2.7 端口耗尽

当某个TCP连接关闭时,会在内存中维护一个小的控制块,用来记录关闭连接端口和IP地址,时间为最大分段使用时间的2倍(2MSL,通常为2分钟)。在这段时间内,该端口不能再建立重复的连接,而端口时有上限的,所以连接速率被限制在60000/120 = 500 次/秒

三、HTTP连接

提高HTTP连接性能的技术:

四、持久连接

HTTP/1.1允许HTTP客户端在事务处理结束之后将TCP连接保持在打开状态,以便为未来的HTTP请求重用现存的连接。

在事务处理结束后仍然保持在打开状态的TCP连接被称为持久连接。

持久连接有两种类型:HTTP/1.0+keep-aliveHTTP/1.1persistent

4.1 使用keep-alive

客户端发送HTTP请求时需加首部connection:keep-alive,如果服务器支持keep-alive,并且同意了持久连接,那么响应的首部也会加入connection:keep-alive,如果服务端不同意持久连接,那么就不会返回这个首部,并且在请求结束后会关闭空闲的TCP连接。响应首部中还会有keep-alive首部对持久连接进行描述:

4.2 使用keep-alive的限制

4.3 keep-alive哑代理

某些代理服务器可能根本不支持keep-alive,但是它转发的时候没有删除客户端的connection:keep-alive,导致服务端以为它想建立持久连接,于是服务端返回keep-alive,代理虽然不知道这个首部是什么意思,于是又转发给了客户端,客户端收到keep-alive后以为服务器同意建立持久连接,但是在复用TCP连接的时候,代理服务器根本不支持持久连接,所以请求就会被挂起。

4.4 proxy-connection

Netscape的浏览器使用proxy-connection替代connection,当低版本代理转发该请求时,直接转发到服务器,服务器不认识该首部,于是直接忽略,但是遇到支持该首部的代理,会把该首部再换成connection,便可以与服务器正常建立持久连接了。

4.5 HTTP/1.1 persistent持久连接

不像HTTP/1.0必须主动声明持久连接,在HTTP/1.1中默认都使用持久连接,除非主动在首部中加入connection:close表示短链接。

4.6 使用persistent

4.7 管道化连接

HTTP/1.1允许在持久连接上使用请求管道,即在响应到达之前,可以将多条请求放入队列,当第一条请求发出之后,第二条第三条等也可以逐个开始发送了。这样做的限制是:

五、关闭连接的奥秘

5.1 任意关闭连接

对于持久连接来说,服务器在该连接的空闲时间的任意时刻都可能关闭该连接,而我们知道HTTP请求可能被分为多个TCP段,那么可能造成一个HTTP请求的部分数据传输出现问题?客户端需要做好错误重传处理!

5.2 重试的幂等性

前面说过,持久连接任何时刻都可能会被关闭,尤其是使用了管道化传输的,在队列中积压了大量的请求,在请求失败后,如果客户端尝试重新打开连接传输,对于非幂等请求可能造成很大的副作用,那么如POSTPUTDELETE等请求方法就不应该使用持久连接管道化传输。

参考文献

[1]《HTTP权威指南》

上一篇下一篇

猜你喜欢

热点阅读