概述
一直以来对于KeepAlive不是很清楚,看到某些框架自己手写了心跳机制,但是一直不明白问什么,设置下keepAlive 不就可以了吗?为什么还要自己维护。
最近研究了下才发现我还是太年轻了。下面看下原因。
1、首先 KeepAlive 机制是TCP 中的概念。KeepAlive 并不是 TCP 协议的一部分,而是大多数操作系统都实现了这个机制,所以一些参数需要我们在操作系统层面设置 。KeepAlive 机制开启后,在一定时间内(一般时间为 7200s,参数 tcp_keepalive_time)在链路上没有数据传送的情况下,TCP 层将发送相应的 KeepAlive 探针以确定连接可用性,探测失败后重试 10(参数 tcp_keepalive_probes)次,每次间隔时间 75s(参数 tcp_keepalive_intvl),所有探测失败后,才认为当前连接已经不可用。
在 Netty 中开启 KeepAlive:
bootstrap.option(ChannelOption.SO_KEEPALIVE, true)
Linux 操作系统中设置 KeepAlive 相关参数,修改 /etc/sysctl.conf 文件:
net.ipv4.tcp_keepalive_time=90
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=2
当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,超过了2个小时,本地的TCP实现会发送一个数据包给远程的 socket,如果远程没有发回响应,TCP会持续尝试11分钟,知道响应为止,如果在12分钟的时候还没响应,TCP尝试关闭socket连接。
keepalive不是说TCP的常连接,当我们作为服务端,一个客户端连接上来,如果设置了keeplive为true,当对方没有发送任何数据过来,超过一个时间(看系统内核参数配置),那么我们这边会发送一个ack探测包发到对方,探测双方的TCP/IP连接是否有效(对方可能断点,断网)。如果不设置,那么客户端宕机时,服务器永远也不知道客户端宕机了,仍然保存这个失效的连接。
当然,在客户端也可以使用这个参数。客户端Socket会每隔段的时间(大约两个小时)就会利用空闲的连接向服务器发送一个数据包。这个数据包并没有其它的作用,只是为了检测一下服务器是否仍处于活动状态。如果服务器未响应这个数据包,在大约11分钟后,客户端Socket再发送一个数据包,如果在12分钟内,服务器还没响应,那么客户端Socket将关闭。如果将Socket选项关闭,客户端Socket在服务器无效的情况下可能会长时间不会关闭。
尽管keepalive的好处并不多,但是很多开发者提倡在更高层次的应用程序代码中控制超时设置和死的套接字。同时需要记住,keepalive不允许你为探测套接字终点(endpoint)指定一个值。所以建议开发者使用的另一种比keepalive更好的解决方案是修改超时设置套接字选项。
说白了:这个参数其实对应用层的程序而言没有什么用。可以通过应用层实现了解服务端或客户端状态,而决定是否继续维持该Socket。
体现在以下几个方面:
(1)KeepAlive 是在应用层面开始,配置再操作系统层面,不够灵活。
(2)KeepAlive是操作系统面向网络层的,对于我们某些应用本身来说大多数情况本非这么简单(例如 频繁fgc 、load 很高、rt很长),对于应用的异常情况,应用已经失去了活性,连接应该被认为是不可用的。但网络仍然是通的。
(3)对于链接异常的情况,TCP会走重传机制,默认的 TCP 超时重传,指数退避算法也是一个相当长的过程。这些情况对于我们的应用来说都是不可接受的。
所以大多数的基于TCP网络框架都是自己写心跳机制,来处理TCP的长链问题。例如Dubbo、jupiter 等rpc框架。
最后
以上就是执着口红为你收集整理的TCP的KeepAlive机制的全部内容,希望文章能够帮你解决TCP的KeepAlive机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复