发出Web请求到服务器都经历了什么(八)HTTP1.1长连接

158 阅读3分钟

在HTTP1.0版本中,如果要发起三次请求,那么需要建立TCP连接(3次握手),发起第一次HTTP请求响应,TCP断开连接(4次挥手),之后再建立TCP连接,发起第二次HTTP请求响应,断开连接,再发起第三次请求,断开连接。这也叫HTTP短连接。

如果是简短的文本请求性能影响不会特别大,但随着图片视频等请求需求增大,因此需要考虑优化不断建立、断开TCP连接的问题。同时因为无效包多也会造成网络拥塞。

Connection:keep-alive

Connection:keep-alive为非标准字段,添加这个字段后,要求服务器不要关闭TCP连接,以便其他请求复用。如果服务器回应了Connection:keep-alive字段,那么一个可以复用的TCP连接就建立了,直到客户端或者服务端主动关闭连接。

keep-alive在应用层传输层的区别

不同层上关注的问题点不同。

  • tcp keep-alive

    传输层的keep-alive。主要为了保活探测,检测连接有效性,判断对方在不在线。

  • http keep-alive

    应用层的keep-alive,为了判断对方能不能提供稳定的应用服务。

keep-alive实现原理

  1. 设置了UTO用户超时时间,按照用户设置的
  2. 没有设置用户超时时间,默认保活探测报文sysctl_tcp_keepalive_probes发送9次,sysctl_tcp_keepalive_intvl两次的间隔重传时间为75s。以及sysctl_tcp_keepalive_time参数,默认7200代表允许连接空闲的时间。默认超时时间=7200+9*75。

HTTP1.1 长连接

97年1月发布的1.1版本。引用了HTTP Persistent Connections(持久连接),TCP连接默认不关闭,将连接保存下来,可以被多个请求复用,直到客户端或者服务端关闭连接。不用声明Connection:keep-alive。关闭方式有两种:

  1. 客户端在最后一个请求时发送Connection:close,明确要求服务器关闭TCP连接
  2. 客户端或者服务端发现对方有一段时间没有活动,就可以主动关闭连接。

注意长连接的时候,HTTP仍然是无状态的,这里只是在TCP层面维持了连接,对于HTTP层面来说要想维持登录信息等,需要使用Cookie、Session等其他方法弥补状态存储问题。

管道机制

HTTP1.1还引入了pipelining管道机制,同一个TCP连接里面,客户端可以发送多个请求,不用等到上一个请求响应后才发送请求。但是响应还是要按照顺序。但是要怎么区分不同请求呢?通过Content-Length字段。

  • Content-Length

    Content-Length会告诉客户端本次回应的长度,后面的自己就属于下一个回应了。但是这样的话服务器在响应的时候就必须要知道数据长度了,对于一些耗时的动态的操作来说效率不高,必须要等到所有操作之后才能完成。因此,引入分块传输编码。

  • 分块传输编码 chunked transfer encoding

    采用“流模式“Stream取代缓存模式buffer。产生一块数据就发送一块数据。因此1.1中可以没有Content-Length字段,只要请求或回应头信息中有Transfer-Encoding字段,就能表明由数量未定的数据块组成。

Transfer-Encoding:chunked

长连接缺点

在同一个TCP连接中,所有数据通信需要按照顺序进行。因此虽然是复用的,但是如果前面的回应特别慢,那么后面就有许多请求排队等着,称为队头堵塞(Head-of-line blocking)。为避免对队头堵塞,可以采取2种方法:

  1. 减少请求数

    例如:雪碧图、合并脚本样式等等,可以减少请求数。

  2. 同时多开持久连接(Chrome中最多同时多开持久连接6个)

    例如:域名分片。