http、tcp的keepalive那些事儿


HTTP keep-alive

早期网页比较简单,一次http请求即可加载到所有资源。随着网页越来越复杂,往往需要多次请求才能加载到所有资源,网页上有css,html,图片等各种资源,短时间内需要多次http请求。每次http请求都需要建立tcp连接、发送请求、接收请求、断开连接等过程,非常耗系统资源.

能不能只建立一次http请求,同时请求css,html,图片等资源?肯定是不能的,因为http是无连接的,如果同一个http请求连续请求css,html,js,图片等,返回的数据就不知道怎么处理了,不知道返回的内容是哪次请求需要的。

那既然tcp连接是有状态的,那能不能只建立一次tcp请求?毕竟tcp请求的握手和分手非常耗网络资源,http请求只是对tcp报文的一个封装,如果能复用tcp请求也能提升不少性能,答案是可以的。

一般用户进入一个网页、浏览网页需要一段时间,但是不会需要很久,因此http keep-alive一般不会设置太长,一般设置成1分钟,即一分钟之内对一个站点的访问只会建立一个tcp连接,页面上如果有多个http请求则会复用这个tcp连接。当没有http请求时,一分钟之后则断开则会个tcp连接。

http keep-alive底层的tcp其实是短链接,它是通过心跳机制着tcp连接不间断

http1.0默认是关闭的,通过http请求头设置“connection: keep-alive”进行开启;http1.1中默认开启,通过http请求头设置“connection: close”关闭

keep-alive机制:若开启后,在一次http请求中,服务器进行响应后,不再直接断开TCP连接,而是将TCP连接维持一段时间。在这段时间内,如果同一客户端再次向服务端发起http请求,便可以复用此TCP连接,向服务端发起请求,并重置timeout时间计数器,在接下来一段时间内还可以继续复用。这样无疑省略了反复创建和销毁TCP连接的损耗。

http keep-alive是在服务端实现的,客户端只是设置了一下http头,加上keep-alive字段,服务端收到这个字段后不会立马关闭tcp连接,会保持一个设置的时长,比如1分钟,1分钟之内如果有新的tcp请求则重置这个时间,否则关闭这个tcp连接。一般服务端会设置两个参数:

  • maxKeepAliveRequests:一个连接上,最多可以发起多少次请求,默认100,超过这个次数后会关闭。
  • keepAliveTimeout:底层socket连接最多保持多长时间,默认60秒,超过这个时间连接会被关闭。
    一般的服务器端都会设置这两个参数,供http keep-alive使用,客户端只需要在http头中开启即可。

TCP keepalive

tcp keepalive是tcp层面的长连接,它是真正的长连接,是传输层,这个tcp长连接可被上层所有协议使用,应用层协议对tcp的长连接无感知,并不直到tcp是长连接,只知道有可用的tcp连接并且使用即可。

tcp长连接默认是关闭的,需要开启。它有三个参数:

  • 保活时间(tcp_keepalive_time)默认:7200秒
  • 保活时间间隔(tcp_keepalive_intvl)默认:75秒
  • 探测循环次数(tcp_keepalive_probes)默认:9次

也就是默认情况下一条TCP连接在2小时(7200秒)都没有报文交换后,会开始进行保活探测,若再经过9*75秒=11分钟15秒的循环探测都未收到探测响应,即共计:2小时11分钟15秒后会自动断开TCP连接。

探测的结果可能有三种情况:

  • 对方回应了ACK。说明一切OK。如果接下来2小时还没有数据传输,那么还会继续发送keepalive探针,以确保连接存活。
  • 对方回复RST,表示这个连接已经不存在。例如一方服务宕机后重启,此时接收到探针,因为不存在对应的连接。
  • 没有回复。说明socket已经被关闭了

tcp的keepalive默认是关闭的,在创建连接的时候可以通过参数设置打开。但是tcp的keepalive一般设置太长,不太实用,一般应用程序自己通过心跳机制来维持着长连接。即tcp创建的时候不设置keepalive,默认它永远连接,它的断开由应用程序主动关闭,只要应用程序不关闭这个tcp连接就不会被断开。在复杂的网络环境下,通过应用程序心跳机制来确保连接保持着通畅,实现应用层的长连接。这是现代很多应用层保持长连接常用的技巧,比如mysql,微服务,服务发现等。

区别

  • TCP连接往往就是我们广义理解上的长连接,因为它具备双端连续收发报文的能力,tcp连接没有长短之分,它只要建立起来了就会永远连接着,除非主动分手,但是由于网络问题,可能有一端会断开连接,这个时候另外一端如果不感知,则会长时间维持着这个无效的连接。所以为了减少无效连接的维护,设置一个keepalive;开启了keep-alive的HTTP连接,也是一种长连接,但是它由于协议本身的限制,服务端无法主动发起应用报文。如果一个http请求结束,马上关闭tcp连接或者长时间不关闭tcp连接,对系统资源都是一种消耗,因此设置一个keep-alive,让这个tcp连接在一段时间内保持着连接状态不要关闭,而这个时间长度是由服务器设置的。
  • TCP中的keepalive是用来保鲜、保活的,tcp本来就是长连接,需要主动关闭才会断开。为了监听对方是否网络通常才设置一个keepalive;HTTP中的keep-alive机制主要为了让支撑它的TCP连接活的的更久,所以通常又叫做:HTTP persistent connection(持久连接) 和 HTTP connection reuse(连接重用)

参考

【1】HTTP keep-alive和TCP keepalive的区别,你了解吗?

【2】详解HTTP 与TCP中Keep-Alive机制的区别


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录