在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实现原理
- 设置了UTO用户超时时间,按照用户设置的
- 没有设置用户超时时间,默认保活探测报文
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。关闭方式有两种:
- 客户端在最后一个请求时发送
Connection:close,明确要求服务器关闭TCP连接 - 客户端或者服务端发现对方有一段时间没有活动,就可以主动关闭连接。
注意长连接的时候,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种方法:
-
减少请求数
例如:雪碧图、合并脚本样式等等,可以减少请求数。
-
同时多开持久连接(Chrome中最多同时多开持久连接6个)
例如:域名分片。