KeepAlive

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KeepAlive相关的知识,希望对你有一定的参考价值。

TCP的keepalive

keepalive是设置在操作系统级别,作用于到本机的连接。在一定时间内对远程主机发送TCP探测报文用于探测对方是否存活。


技术分享图片

上图2个场景是最常见的,但是针对于keepalive的问题是一样的。无非就是客户端和最终的WEB服务器直接多了中间设备。这会怎么样呢?正常情况下不会有问题,但是客户端把请求发送给nginx,Nginx的后端Tomcat需要一定时间才能返回结果,超过90秒就会有问题,如果使用LVS做负载均衡看到的现象就是90秒内没有返回则LVS会把客户端到Nginx的连接断开。因为LVS默认保持的TCP会话为90秒。超过90秒没有TCP传输,LVS就会给客户端和Nginx发送RESET报文断开连接。这样做的原因其实就是节省资源关闭空闲连接和保护后端。遇到这种请求你只需要在LVS上开启keepalive就好,当然你的Nginx上也要设置,因为真正的后端服务器是Tomcat等应用程序。

keepalive是什么:

连接建立以后,如果应用程序或上层协议一直不发数据或者间隔很久才发一次,那么如何确定建立连接的双方还存在呢?在TCP协议的设计中,在一段时间之后,TCP自动发送一个空数据报文给对方,如果对方回应了这个报文说明还在线,那么继续保持连接,如果对方没有回应并且经过多次重试发送之后依然没有回应,则认为对方不在线可以关闭连接。

如何开启keepalive:

keepalive在Linux系统上没有一个全局开关来开启或关闭这个功能以为它是TCP的一个特性,所以不能简单的说默认是不是开启。因为开启这个功能是需要应用程序在注册使用socket时单独设置的,Linux上关于TCP的内核参数只是会影响keepalive的行为。注意:启动Nginx或者LVS等任何网络服务都会使用socket。

sysctl -a | grep net.ipv4.tcp_keepalive

技术分享图片

参数
含义
net.ipv4.tcp_keepalive_intvl
表示发送前一个探测报文和后一个探测报文的间隔时间
net.ipv4.tcp_keepalive_probes表示探测次数,超过这个次数还是探测失败则关闭连接
net.ipv4.tcp_keepalive_time表示TCP连接多少秒之后没有数据报文传输就启动探测报文

代码体现

setsockopt函数是设置与套接字有关的选项,它里面的选项有很多,下面的SO_KEEPALIVE表示长连接。

//使用长连接
if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1)
{
    //if error
}

//设置选项
if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1)
{
    //if error
}

if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1)
{
    //if error
}

if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1)
{
    //if error
}
socket选项
对应的内核参数
TCP_KEEPCNT
net.ipv4.tcp_keepalive_probes
TCP_KEEPIDLE
net.ipv4.tcp_keepalive_time
TCP_KEEPINTVL
net.ipv4.tcp_keepalive_intvl

Linux系统对这三个参数有默认设置,你的应用程序可以覆盖自行设置需要的值。


HTTP的keep-alive

HTTP的keep-alive和TCP的不是一个概念,一个页面上有几百个元素一个元素其实就是一个HTTP请求,如果每个请求都打开和关闭一次TCP连接那相当消耗资源,对于HTTP的Keep-Alive来说就是TCP连接的复用,一个请求完毕后服务器不关闭连接而是等待一段时间接收浏览器可能发来的之后的请求。通常浏览器在完成第一个请求之后会马上发送第二个请求,所以这样会节省很多资源消耗。

Nginx如何开启keep-alive呢?

从TCP层面上Nginx要关系和client和后端upstream的KeepAlive,同时从HTTP层面Nginx还需要关系client和upstream的keep-alive。

参数
说明
keepalive_timeout
0表示关闭keepalive,设置大于0的值表示保持链接多少秒,这个值不能解决TCP层面的KeepAlive问题
keepalive_requests
一个长连接建立之后,Nginx会给客户端计数,达到数值时则关闭连接。默认100,对于QPS比较高的场景这个值可以设置大一点。
so_keepalive

on|off|[keepidle]:[keepintvl]:[keepcnt]

on表示开启 off表示关闭  keepidle表示等待时间   keepintvl表示探测报文发送间隔时间  keepcnt表示探测报文发送次数

以上参数只能用一个。该参数属于listen的辅助参数,在server端中,配置完监听端口可以使用这个参数。

listen 80 so_keepalive=on,如果要设置时间可以这样设置

listen 80 so_keepalive=30::10  

总结

HTTP的keep-alive是为了让TCP连接存活久一点以便复用连接完成更多HTTP请求,提高连接利用率。

TCP的Keepalive是一种TCP连接的探测机制,使其一直保持可用。

以上是关于KeepAlive的主要内容,如果未能解决你的问题,请参考以下文章

vue中手动清除KeepAlive缓存

一些滚动后颤动ListView KeepAlive

python socket处理keepalive请求

keepalive高可用的健康检查

asyncio HTTP服务器挂起keepalive

用pinia和<KeepAlive;时需要注意Cache被改写的问题