12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
讲述:冯永吉
时长12:09大小11.14M
从一个例子开始
TCP Keep-Alive 选项
应用层探活
消息格式设计
客户端程序设计
服务器端程序设计
实验
总结
思考题
赞 8
提建议
精选留言(46)
- 传说中的成大大置顶2019-08-28思考题 1. udp不需要连接 所以没有必要心跳包 2. 我觉得还是很有必要判定存活 像以前网吧打游戏 朋友的电脑突然蓝屏死机 朋友的角色还残留于游戏中,所以服务器为了判定他是否真的存活还是需要一个心跳包 隔了一段时间过后把朋友角色踢下线
作者回复: 2是一个很好的例子。
共 5 条评论19 - fjpcode2019-08-281.UDP里面各方并不会维护一个socket上下文状态是无连接的,如果为了连接而保活是不必要的,如果为了探测对端是否正常工作而做ping-pong也是可行的。 2.额外的探活报文是会占用一些带宽资源,可根据实际业务场景,适当增加保活时间,降低探活频率,简化ping-pong协议。 3.多次探活是为了防止误伤,避免ping包在网络中丢失掉了,而误认为对端死亡。
作者回复: 👍
共 2 条评论44 - 扩散性百万咸面包2020-04-17想到HTTP Header也能设置Connection: Keep-Alive,也是应用层协议,是不是底层实现也类似于定时器+Ping Pong的思路?
作者回复: HTTP的 keep-alive是为了使http变成长连接,在此前的http 1.0中,每次http的请求-响应之后,tcp连接就会被释放掉,这显然是非常浪费的,于是通过加入keep-alive,使得http连接不会被立即释放。
16 - 云师兄2019-12-17文章中提到保活有两个方向,实际应用中,会有两个方向同时探测的场景吗
作者回复: 当然有。服务器端要探活client来保证自己不会维护无效连接,客户端来探活保持自己是不是可以持续申请资源。
8 - 满怀2019-12-20老师 我想问一下 看您在回复当中有说 虽然TCP本身的keep-alive机制可以设置保活时间,保活探测时间间隔以及探测次数,但是应用层会无法感知,那么这种情况下会怎么处理呢 就是文中所给出的三种情况吗
作者回复: 是的,大部分的应用程序开发者都会选择自己在应用层处理连接有效性的检测。
6 - 徐凯2019-09-06老师 同步连接可以实现心跳包么 如果不能的话 那同步连接如果因为客户端崩溃 没有通过四次挥手结束连接 服务端还堵塞在接收数据 那么这样如何判断对方已经离开呢
作者回复: 首先,客户端应用程序崩溃是可以有FIN包的,如果有的话,read阻塞就可以返回了;其次,如果真的是客户端机器跪了,那么是没有FIN包发出的,这个时候,我们只好一直在那里傻等。 且慢,还有别的辙,那就是不要用阻塞I/O,不要在哪里傻傻等待。使用I/O复用就可以办到的,往后看就会明白了。
共 3 条评论6 - rongyefeng2020-05-18服务器端恢复心跳包这段 case MSG_PING: { messageObject pong_message; pong_message.type = MSG_PONG; sleep(sleepingTime); ssize_t rc = send(connfd, (char *) &pong_message, sizeof(pong_message), 0); 老师,这个type是int类型,应该将其转为网络序才对吧? pong_message.type = htonl(MSG_PONG); 而且你的客户端程序也是有转换的,是不是服务器端这里忘记了?展开
作者回复: Bingo。确实是我忘记了:)
3 - HunterYuan2019-12-17对于协议栈中的TCP的keep-alive是可以手动配置的,全局配置通过修改net.ipv4下的等参数;局部配置可以通过setsockopt修改socket选项。在工作中遇到过一个oracle,windows服务器的保活时间大于,我们设备状态连接表的保活时间,导致,一段时间后重连,导致服务器报错问题。当时最最快的处理办法是,修改window默认的保活时间小于状态连接失效时间。
作者回复: 学习了。
4 - 石将从2019-08-29为啥这句套接字要加1呢?int rc = select(socket_fd + 1, &readmask, NULL, NULL, &tv);
作者回复: 这是因为,嗯,跟select实现有关,我再后面讲select时详细剖析,现在先记住吧。
共 4 条评论3 - 郑祖煌2020-07-02这个是客户端探活服务器是否还存活,还可以用服务器来探活客户端是否还存活。我原先也有接触过这个心跳,不过实现的机制比较简单,就是客户端连上服务器了,客户端要每个M秒向服务器发包,服务器如果在M+10秒内没收到这个心跳包就判定客户端已经死亡。就会在应用层方面判定客户端已经失去连接。
作者回复: 没有服务器到客户端的反向连接检测么?M+10秒有点狠啊。
1 - 刘士涛2020-03-19请问老师一个tcp长连接,网络发生故障, client和server都还没有断开这个连接, 这时候client调用send发送数据是个什么行为?我理解send进缓冲区是一直成功的, 但是由于网络不通, 数据不会发出去。这时候如果想要发现这个tcp断开就只能client应用层设置一个超时, 超时后调用shutdown, 有其他的方式可以感知到这个tcp断开么
作者回复: 应用层设置ping-pang的操作,如果在一段时间内没有应用层心跳报文,认为tcp已经断开。
共 4 条评论1 - Geek_d6f50f2020-01-05老师,第二次运行程序,客户端的定时器设定为每10秒钟进行一次select返回0,此时进行探测包发送。而服务器端延迟5秒进行应答,为什么客户端每次都能发送两个包后才清零?不应该是只进行一个包的发送,服务器端延迟5秒就给出应答,然后清零吗?
作者回复: 是这样的, 当客户端10秒钟select超时时间到达,第一次进入heartbeat,发送报文给服务器端,同时客户端把下一次select超时时间设置为3秒(KEEP_ALIVE_INTERVAL); 由于服务器端是5秒之后才回复,3秒之后,第二次heartbeat时间到,客户端发送第二个heartbeat。 5秒之后,第一次的heartbeat回复到,客户端把超时时间又重新设置为10秒。 再过5秒之后,第二次的heartbeat回复到,客户端把超时时间再次设置为10秒。 如此反复。
2 - 衬衫的价格是19美元2019-10-04tcp探活的目的之一是判断该连接是否还需要,以此决定是维持还是释放该连接资源。udp无连接,也不占用服务器或者客户端的资源,因此业务无需探活1
- 徐凯2019-08-29我看到大家对于第二个问题的答案都提到了为了避免探活包丢包 所以要发多个探活包。但是我觉得只要发了探活包对方就一定能收到,就算丢了 发送端也会重传。而大家说的发送多个探活包的原因 是因为重传需要等到计时器超时才传,而如果网络堵塞的话可能会出现频繁丢包 那么服务端可能需要很久才能知道对方已经离开 发多个探活包的话 就减少了这个等待的时间 这样理解对么
作者回复: 探活包的多次发送,还是为了减少误判的概率,你说的是一种情况,但我觉得多此探活肯定会拉长对一个"无效"连接的判断时间的。这个是一个tradeoff,所以大多数程序都把这个作为选项让使用者自己配置。
共 2 条评论1 - LDxy2019-08-28TCP本身的keep-alive的时间是可以自己设置的吗?如果是可以自己设置的,为何还需要自己实现这个机制?
作者回复: 可以设置的,但是有时候应用层需要感知处理这样的异常
1 - 张贺龙2022-09-19 来自上海保活是应用层的动作可以用于udp,在数据中心集群中多个主机的通讯也有使用udp通讯的场景,保活的作用还是相当大的;保活会占用额外带宽,但由于只在无业务消息时传送,因此不会影响正常业务信息的传送;多次确认是为了避免偶然网络抖动造成的消息传送超时
- 德鲁小叔2021-11-11老师你在留言里面回复,很多实际的场景都是自己在应用层加心跳,这个是指http的keep-alive么?如果是在java开发的应用,这个心跳是指客户端定时向服务端发起请求么?可不可以结合一下java应用举一个例子
作者回复: http的keep-alive不是我这里的心跳。 我这里的意思是指,通过在客户端-服务器之间发送定期的报文,用来检查连接的有效性。不一定是客户端发给服务器,服务器端也可以发送给客户端。在很多程序里都叫做"ping-pang"报文。
- 凌空飞起的剪刀腿2021-05-19老师我想问一下, 连接无效:使用Keep-Alive还是应用心跳来检测? 是不是应该使用应用心跳来检测,比使用Keep-Alive更好啊?
作者回复: 只能说,很多实际的场景都是自己在应用层加心跳来解的。没有好不好,是大家总结出来的行之有效的方法。
- 守望2020-08-11老师您好,有个问题想请教一下,假设服务端重启了,起来后还是绑定同样的ip和端口,而客户端仍然发送,如何最大程度的避免客户端发送数据丢失呢?这种心跳检测貌似发现过慢。
作者回复: 你说的这种情况,连接是需要重建建立的,心跳检测如果觉得慢,可以通过设置不同的处理逻辑来加速,比如一旦发现连接异常,就立即启动一个补偿机制,短时间内进行重连。
共 2 条评论 - 饭2020-06-28老师,一台服务器同时在线的tcp/ip连接数,理论上是不是最多只有65535个?
作者回复: 你的结论是来自端口号的限制么?如果是这样的话,我觉得是一个错误的结论。后面章节讲到的C10K/C10M问题,就是在研究单机上的连接达到10K、10M的技术。
共 3 条评论