连接管理

1. TCP连接

HTTP连接实际上就是TCP连接和一些使用连接的规则。
TCP连接是因特网上的可靠连接。TCP为HTTP提供了一条可靠的比特传输管道。从TCP连接一端填入的字节会在另一端以原有的顺序、正确地传送出来。

TCP流是分段的、由IP分组传送的。HTTPS在HTTP层与TCP层之间增加了一个称为TSL或SSL的密码加密层。


连接管理_第1张图片
HTTP与HTTPS

HTTP要传送一条报文时,会以流的形式将报文数据的内容通过一条打开的TCP连接按序传输。TCP收到数据流之后,会将数据流砍成被称作段的小数据块,并将段封装在IP分组中,通过因特网进行传输。
每个TCP段都是由IP分组承载,从一个IP地址发送到另一个IP地址的。每个IP分组中都包括:

  • 一个IP分组首部(通常为20字节)
  • 一个TCP分组首部(通常为20字节)
  • 一个TCP数据块(0个或多个字节)

IP首部包含了源和目的IP地址、长度和其它一些标记。TCP段的首部包含了TCP端口号、TCP控制标记,以及用于数据排序和完整性检查的一些数值。
在任意时刻,每一个计算机都可以有几条TCP连接处于打开状态。TCP连接是通过4个值来识别的:
<源IP地址、源端口号、目的IP地址、目的端口号>
这4个值一起唯一地定义了一条连接。

2. 影响HTTP性能的因素

  • DNS解析时延
  • TCP握手时延
  • HTTP报文请求、处理与响应时延
  • 延迟确认
    由于因特网自身无法确保可靠的分组传输(因特网路由器超负荷的话,可以随意丢弃分组),所以TCP实现了自己的确认机制来确保数据的成功传输。
    每个TCP段都有一个序列号和数据完整性校验和。每个段的接受者接收到完好的段时,都会向发送者回送小的确认分组。如果发送者没有在指定的窗口时间内收到确认信息,发送者就认为分组已被破坏或损毁,并重发数据。
    由于确认分组很小,为了有效地利用网络,TCP允许在发往相同方向的输出数据分组中对其进行“捎带”。为了增加确认报文找到同向传输数据分组的可能性,很多TCP栈都实现了一种“延迟确认”算法。“延迟确认”算法会在一个特定的窗口时间内(通常是100~200毫秒)将输出确认存放到缓冲区中,以寻找能够捎带它的输出数据分组。如果在那段时间内没有输出数据分组,就将输出确认放在单独的分组中传送。
  • 慢启动拥塞控制
  • Nagle算法
    Nagle鼓励发送全尺寸的段。只有当所有其他分组都被确认之后,Nagle算法才允许发送非全尺寸的分组。
    Nagle算法会引起几种HTTP性能问题。首先,小的HTTP报文可能无法填满一个分组,可能会因为等待那些永远都不会到来的额外数据而产生时延。其次,Nagle算法与延迟确认之间的交互存在交互问题——Nagle算法会阻止数据的发送,直到有确认分组到达为止,但确认分组自身会被“延迟确认”算法延迟100~200毫秒。
  • TIME_WAIT时延和端口耗尽

3. HTTP性能的提升方式

  • 并行连接
    并行连接的速度可能会更快,但不一定总是更快。而且,打开大量连接会消耗很多内存资源,从而引发自身的性能问题。实际上,浏览器确实使用了并行连接,但它们会将并行连接的数量限制在一个较小的值(通常是4个)。服务器可以随意关闭来自特定客户端的超量连接。
    并行连接的缺点:
  • 每个事务都会打开/关闭一条新的连接,会耗费时间和带宽
  • 由于TCP慢启动特性的存在,每条连接的性能都会有所降低
  • 可打开的并行连接的数量实际上是有限的
  • 持久连接
    在事务处理结束之后仍然保持在打开状态的TCP连接被称为持久连接。重用已对目标服务器打开的空闲持久连接,可以避开缓慢的连接建立阶段。而且,已经打开的连接还可以避免慢启动的拥塞适应阶段,以便更快速地进行数据的传输。
    持久连接配合并行连接使用可能是最高效的方式。现在,很对Web应用程序都会打开少量的并行连接,每一条并行连接都是持久连接。
    持久连接有两种类型:比较老的HTTP/1.0+“keep-alive”连接,以及现代的HTTP/1.1“persistent”连接。
  • HTTP/1.0+ “keep-alive”连接
    实现HTTP/1.0 keep-alive连接的客户端可以通过包含Connection: Keep-Alive首部请求将一条连接保持在打开状态。
    如果服务器愿意为下一条请求将连接保持在打开状态,就在响应中包含相同的首部。如果响应中没有Connection: Keep-Alive首部,客户端就认为服务端不支持keep-alive,会在发回响应报文之后将连接关闭。
    Keep-Alive选项
  1. 参数timeout是在Keep-Alive响应首部发送的。它估计了服务器希望将连接保持在活跃状态的时间。这并不是一个承诺值。
  2. 参数max是在Keep-Alive响应首部发送的。它估计了服务器还希望为多少个事务保持此连接的活跃状态。这并不是一个承诺值。
  • HTTP/1.1 “persistent”连接
    与HTTP/1.0+的Keep-Alive连接不同,HTTP/1.1的持久连接在默认情况下是激活的。要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显示地添加一个Connection: close首部。
  • 管道化连接
    HTTP/1.1允许在持久连接上可选地使用请求管道。在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络流向另一端的服务器时,第二条和第三条请求也可以开始发送了。在高时延网络环境下,这样做可以降低网络的环回时间,提高性能。
    使用管道化连接的限制:
  • 如果HTTP客户端无法确认连接是持久的,就不应该使用管道。
  • 必须按照与请求相同的顺序回送HTTP响应。
  • HTTP客户端必须做好连接会在任意时刻关闭的准备,还要准备好重发所有未完成的管道化请求。
  • HTTP客户端不应该用管道化的方式发送会产生副作用的请求(比如POST)。因为出错的时候,客户端无法了解服务端到底执行了请求序列中的哪些请求,而像POST这种非幂等请求是不能随便地重试的,所以出错时,就存在某些方法永远不会被执行的风险。

4. 正确地关闭连接

  • Content-Length及截尾操作
    每条HTTP响应都应该有精确的Content-Length首部,用以描述响应主体的尺寸。一些老的HTTP服务器会省略Content-Length首部或者包含错误的长度指示,这样就要依赖服务器发出的连接关闭来说明数据的真实结尾。
  • 正常关闭连接
    实现正常关闭的应用程序应该首先关闭它们的输出信道,然后等待连接另一端的对等实体关闭它的输出信道。当两端都告诉对方它们不会再发送任何数据之后,连接就会被完全关闭。

你可能感兴趣的:(连接管理)