为什么会有keep alive的出现?
初期http请求,每个请求建立一个连接,请求/响应,关闭连接,耗时
1、每次http请求都要创建连接(三次握手),创建连接是需要耗时和资源
因为每次请求完成,就会关闭连接,下一次请求又要重新创建连接
2 、减少耗时和耗资源,于是出现了keep alive,数据请求完不要关闭连接,继续保持
优点: 下一次请求不用三次握手直接发送请求
缺点: 一直保持长连接,系统资源一直被占用浪费
HTTP/1.1 默认
Connection: keep-alive // 服务器也要支持
解决keep alive缺点
长连接,资源浪费?
1 、设置超时时间,超过时间主动关闭连接
2、设置最大请求数,超过及时未到时,也关闭连接
http的keep alive
- HTTP/1.1 默认开启
- 浏览器开启后,能够复用TCP连接
复用,就不用在经历耗时的三次握手建立连接,直接发送请求(携带数据)
这里注意,建立tcp连接之前,请求是不会携带数据的
tcp的keep alive
TCP keepalive指的是TCP保活计时器(keepalive timeout)。设想有这样的情况:客户已主动与服务器建立了TCP连接。但后来客户端的主机突然出故障。显然,服务器以后就不能再收到客户发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就是使用保活计时器。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75秒发送一次。若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。
tpc配置参数
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_time = 1800
简单说: 没有收到数据活着一次响应完成后,再tcp_keepalive_time后,服务器向客户端发送侦测包,判断来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该TCP连接
cat /proc/sys/net/ipv4/tcp_keepalive_time
7200 当keepalive启用的时候,TCP发送keepalive消息的频度。缺省是2小时
cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75
当探测没有确认时,重新发送探测的频度。缺省是75秒
cat /proc/sys/net/ipv4/tcp_keepalive_probes 9
探测尝试的次数。如果第1次探测包就收到响应了,则后8次的不再发
设置keep alive后,浏览器如何判断一次请求已经完成
- content length
浏览器通过content length字段来判断当前请求的数据是否已经全部接收
比如Content-Length: 120表示响应体内容有120个字节
这样浏览器接收到120个字节的响应体后就知道了已经响应完成
注意这里有坑:
content length: 实体传输长度
如果文件压缩过: 实体传输长度和实体长度不一样
实体长度: 压缩前的长度
传输长度: 压缩后的长度
(所以过短截断,过长超时)
- Transfer-Encoding
content length必须知道实体长度,有时响应体来自网络文件
这时,要知道准确长度,必须开辟足够大的内存,内容全部生成好了再计算
这样不仅开销额外内存,还需要让客户端就等
于是:Transfer-Encoding: chunked出现
1、服务器讲数据分块发给浏览器
2、浏览器接收到长度为0的chunked表示当前内容已经全部接受完毕
- 注意
1、http1.1及之后版本content length和Transfer-Encoding 不能同时存在,必须二选一
2、有Transfer-Encoding 即使有conten length也会被忽略
3、用content length,传输和内容长度必须一样