心跳

保持对连接有效性的检测

TCP Keep-Alive 选项

TCP的keepalive是侧重在保持客户端和服务端的连接,一方会不定期发送心跳包给另一方,当一方端掉的时候,没有断掉的定时发送几次心跳包,如果间隔发送几次,对方都返回的是RST,而不是ACK,那么就释放当前链接。设想一下,如果tcp层没有keepalive的机制,一旦一方断开连接却没有发送FIN给另外一方的话,那么另外一方会一直以为这个连接还是存活的,几天,几月。那么这对服务器资源的影响是很大的。

原理

  1. TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡。
  2. 上述的可定义变量,分别被称为保活时间、保活时间间隔和保活探测次数。在 Linux 系统中,这些变量分别对应 sysctl 变量
net.ipv4.tcp_keepalive_time、默认设置是 7200 秒(2 小时)、
net.ipv4.tcp_keepalive_intvl、 75 秒
net.ipv4.tcp_keepalve_probes, 9 次探测。
如果开启了 TCP 保活,需要考虑以下几种情况:
  • 第一种,当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置。
  • 第二种,对端程序崩溃并重启。对端会产生一个 RST 报文,这样很快就会发现 TCP 连接已经被重置。
  • 第三种,是对端程序崩溃,或其他原因导致报文不可达,连续几次达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。

TCP 保活机制默认是关闭的,当我们选择打开时,可以分别在连接的两个方向上开启,也可以单独在一个方向上开启。如果开启服务器端到客户端的检测,就可以在客户端非正常断连的情况下清除在服务器端保留的“脏数据”;而开启客户端到服务器端的检测,就可以在服务器无响应的情况下,重新发起连接。

1.应用层探活

为什么这么做?

  • eepalive只能检测连接是否存活,不能检测连接是否可用。例如,某一方发生了死锁,无法在连接上进行任何读写操作,但是操作系统仍然可以响应网络层keepalive包。
  • TCP keepalive 机制依赖于操作系统的实现,灵活性不够,默认关闭,且默认的 keepalive 心跳时间是 两个小时, 时间较长。
  • 代理(如socks proxy)、或者负载均衡器,会让tcp keep-alive失效
    基于此,我们往往需要加上应用层的心跳。

解决:通过在应用程序中模拟 TCP Keep-Alive 机制,来完成在应用层的连接探活。

  • 设计一个 PING-PONG 的机制,需要保活的一方,比如客户端,在保活时间达到后,发起对连接的 PING 操作,如果服务器端对 PING 操作有回应,则重新设置保活时间,否则对探测次数进行计数,如果最终探测次数达到了保活探测次数预先设置的值之后,则认为连接已经无效。
  • 第一个是需要使用定时器,这可以通过使用 I/O 复用自身的机制来实现;第二个是需要设计一个 PING-PONG 的协议。
2.消息格式设计

我们的程序是客户端来发起保活,为此定义了一个消息对象。这个消息对象是一个结构体,前 4 个字节标识了消息类型,为了简单,这里设计了MSG_PING、MSG_PONG、MSG_TYPE 1和MSG_TYPE 2四种消息类型。

typedef struct {
    u_int32_t type;
    char data[1024];
} messageObject;

#define MSG_PING  1
#define MSG_PONG  2
#define MSG_TYPE1 11
#define MSG_TYPE2 21
总结:

虽然TCP 没有提供系统的保活能力,让应用程序可以方便地感知连接的存活,但是,可以在应用程序里灵活地建立这种机制这种机制的建立依赖于系统定时器,以及恰当的应用层报文协议。比如,使用心跳包就是这样一种保持 Keep Alive 的机制。

问题:

1.探活是否同样适用于 UDP 呢?

  • UDP里面各方并不会维护一个socket上下文状态是无连接的,如果为了连接而保活是不必要的,如果为了探测对端是否正常工作而做ping-pong也是可行的。

2.有人说额外的探活报文占用了有限的带宽,对此你是怎么想的呢?而且,为什么需要多次探活才能决定一个 TCP 连接是否已经死亡呢?

  • 还是很有必要判定存活 像以前网吧打游戏 朋友的电脑突然蓝屏死机 朋友的角色还残留于游戏中,所以服务器为了判定他是否真的存活还是需要一个心跳包 隔了一段时间过后把朋友角色踢下线
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值