当前位置:首页 > 公众号精选 > 小林coding
[导读]如果「服务端挂掉」指的是「服务端进程崩溃」,那么这个读者猜的想法是对的,服务端的进程在发生崩溃的时候,内核会发送 FIN 报文,与客户端进行四次挥手。

收到一位读者的私信,说字节面试有这么一个问题:服务端挂了,客户端的 TCP 连接会发生什么?

如果「服务端挂掉」指的是「服务端进程崩溃」,那么这个读者猜的想法是对的,服务端的进程在发生崩溃的时候,内核会发送 FIN 报文,与客户端进行四次挥手。

但是,如果「服务端挂掉」指的是「服务端主机宕机」,那么是不会发生四次挥手的,具体后续会发生什么?还要看客户端会不会发送数据?

  • 如果客户端会发送数据,由于服务端已经不存在,客户端的数据报文会超时重传,当重传次数达到一定阈值后,会断开 TCP 连接;
  • 如果客户端一直不会发送数据,再看客户端有没有开启 TCP keepalive 机制?
    • 如果有开启,客户端在一段时间后,检测到服务端的 TCP 连接已经不存在,则会断开自身的 TCP 连接;
    • 如果没有开启,客户端的 TCP 连接会一直存在,并不会断开。

上面属于精简回答了,下面我们详细聊聊。

服务端进程崩溃,客户端会发生什么?

TCP 的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有 TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成 TCP四次挥手的过程。

我自己也做了实验,使用 kill -9 命令来模拟进程崩溃的情况,发现在 kill 掉进程后,服务端会发送 FIN 报文,与客户端进行四次挥手

服务端主机宕机后,客户端会发生什么?

当服务端的主机突然断电了,这种情况就是属于服务端主机宕机了。

当服务端的主机发生了宕机,是没办法和客户端进行四次挥手的,所以在服务端主机发生宕机的那一时刻,客户端是没办法立刻感知到服务端主机宕机了,只能在后续的数据交互中来感知服务端的连接已经不存在了。

因此,我们要分两种情况来讨论:

  • 服务端主机宕机后,客户端会发送数据;
  • 服务端主机宕机后,客户端一直不会发送数据;

服务端主机宕机后,如果客户端会发送数据

在服务端主机宕机后,客户端发送了数据报文,由于得不到响应,在等待一定时长后,客户端就会触发超时重传机制,重传未得到响应的数据报文。

当重传次数达到达到一定阈值后,内核就会判定出该 TCP 连接有问题,然后通过 Socket 接口告诉应用程序该 TCP 连接出问题了,于是客户端的 TCP 连接就会断开。

那 TCP 的数据报文具体重传几次呢?

在 Linux 系统中,提供了一个叫 tcp_retries2 配置项,默认值是 15,如下图:

这个内核参数是控制,在 TCP 连接建立的情况下,超时重传的最大次数。

不过 tcp_retries2 设置了 15 次,并不代表 TCP 超时重传了 15 次才会通知应用程序终止该 TCP 连接,内核会根据 tcp_retries2 设置的值,计算出一个 timeout如果 tcp_retries2 =15,那么计算得到的 timeout = 924600 ms),如果重传间隔超过这个 timeout,则认为超过了阈值,就会停止重传,然后就会断开 TCP 连接

在发生超时重传的过程中,每一轮的超时时间(RTO)都是倍数增长的,比如如果第一轮 RTO 是 200 毫秒,那么第二轮 RTO 是 400 毫秒,第三轮 RTO 是 800 毫秒,以此类推。

而 RTO 是基于 RTT(一个包的往返时间) 来计算的,如果 RTT 较大,那么计算出来的 RTO 就越大,那么经过几轮重传后,很快就达到了上面的 timeout 值了。

举个例子,如果 tcp_retries2 =15,那么计算得到的 timeout = 924600 ms,如果重传总间隔时长达到了 timeout 就会停止重传,然后就会断开 TCP 连接:

  • 如果 RTT 比较小,那么 RTO 初始值就约等于下限 200ms,也就是第一轮的超时时间是 200 毫秒,由于 timeout 总时长是 924600 ms,表现出来的现象刚好就是重传了 15 次,超过了 timeout 值,从而断开 TCP 连接
  • 如果 RTT 比较大,假设 RTO 初始值计算得到的是 1000 ms,也就是第一轮的超时时间是 1 秒,那么根本不需要重传 15 次,重传总间隔就会超过 924600 ms。

最小 RTO 和最大 RTO 是在 Linux 内核中定义好了:

#define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) 

Linux 2.6+ 使用 1000 毫秒的 HZ,因此TCP_RTO_MIN约为 200 毫秒,TCP_RTO_MAX约为 120 秒。

如果tcp_retries设置为15,且  RTT 比较小,那么 RTO 初始值就约等于下限 200ms,这意味着它需要 924.6 秒才能将断开的 TCP 连接通知给上层(即应用程序),每一轮的 RTO 增长关系如下表格:

服务端主机宕机后,如果客户端一直不发数据

在服务端主机发送宕机后,如果客户端一直不发送数据,那么还得看是否开启了 TCP keepalive 机制 (TCP 保活机制)。

如果没有开启 TCP keepalive 机制,在服务端主机发送宕机后,如果客户端一直不发送数据,那么客户端的 TCP 连接将一直保持存在,所以我们可以得知一个点,在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。

而如果开启了 TCP keepalive 机制,在服务端主机发送宕机后,即使客户端一直不发送数据,在持续一段时间后,TCP 就会发送探测报文,探测服务端是否存活:

  • 如果对端是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
  • 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡

所以,TCP keepalive 机制可以在双方没有数据交互的情况,通过探测报文,来确定对方的 TCP 连接是否存活。

TCP keepalive 机制具体是怎么样的?

TCP keepalive 机制机制的原理是这样的:

定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序

在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75  
net.ipv4.tcp_keepalive_probes=9

每个参数的意思,具体如下:

  • tcp_keepalive_time=7200:表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制
  • tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
  • tcp_keepalive_probes=9:表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。

也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。

注意,应用程序如果想使用 TCP 保活机制,需要通过 socket 接口设置 SO_KEEPALIVE选项才能够生效,如果没有设置,那么就无法使用 TCP 保活机制。

TCP keepalive 机制探测的时间也太长了吧?

对的,是有点长。

TCP keepalive 是 TCP 层(内核态) 实现的,它是给所有基于 TCP 传输协议的程序一个兜底的方案。

实际上,我们应用层可以自己实现一套探测机制,可以在较短的时间内,探测到对方是否存活。

比如,web 服务软件一般都会提供 keepalive_timeout参数,用来指定 HTTP 长连接的超时时间。如果设置了 HTTP 长连接的超时时间是 60 秒,web 服务软件就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。

总结

如果「服务端挂掉」指的是「服务端进程崩溃」,服务端的进程在发生崩溃的时候,内核会发送 FIN 报文,与客户端进行四次挥手。

但是,如果「服务端挂掉」指的是「服务端主机宕机」,那么是不会发生四次挥手的,具体后续会发生什么?还要看客户端会不会发送数据?

  • 如果客户端会发送数据,由于服务端已经不存在,客户端的数据报文会超时重传,当重传总间隔时长达到一定阈值(内核会根据 tcp_retries2 设置的值计算出一个阈值)后,会断开 TCP 连接;
  • 如果客户端一直不会发送数据,再看客户端有没有开启 TCP keepalive 机制?
    • 如果有开启,客户端在一段时间没有进行数据交互时,会触发 TCP keepalive 机制,探测对方是否存在,如果探测到对方已经消亡,则会断开自身的 TCP 连接;
    • 如果没有开启,客户端的 TCP 连接会一直存在,并且一直保持在 ESTABLISHED 状态。

还有另外一个很有意思的问题:「拔掉网线几秒,再插回去,原本的 TCP 连接还存在吗?」,之前我也写过,可以参考这篇:拔掉网线几秒,原本的 TCP 连接还存在吗?

完!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

业内消息,近日高通公司宣布推出针对桌面平台的全新骁龙 X Plus 处理器。

关键字: 高通 骁龙 X Plus 处理器

近日,台积电在圣克拉拉年度技术研讨会上宣布首个“埃级”制程技术:A16。A16 是台积电首次引入背面电源输送网络技术,计划于 2026 年下半年开始量产。同时,台积电也在重新命名工艺节点,标志着「埃级」时代的开始。

关键字: 台积电 A16

4 月 25 日消息,4 月 25 日,国际数据公司(IDC)发布 2024 年第一季度中国手机市场跟踪报告,荣耀以 17.1% 的市场份额拿下第一,华为占 17.0% 位列第二,OPPO、苹果和 vivo 分别位列第三...

关键字: 荣耀 华为

业内消息, 近日华为全新Pura 70系列手机正式开售引发广大 数码爱好者追捧,但是有网友注意到这款手机的“AI修图”功能,竟然可以将照片中的人物衣服消除,并拍成视频发布网络。

关键字: 华为Pura70 华为

据韩媒报道,近日韩国多位军方人士透露,韩国军方正在考虑全面禁止在军事建筑内使用苹果手机,军方担心敏感信息通过录音泄露。

关键字: iPhone 苹果

据韩媒《朝鲜日报》消息,三星集团已确认已决定将适用于三星电子等部分关联公司的“高管每周工作 6 天”扩大到整个集团。三星子公司的人力资源团队直接通过口头、群聊和电子邮件向高管传达了这一新政,而非正式信函的形式。

关键字: 三星

4月23日,深圳传音控股股份有限公司发表了2023年年度报告。数据显示,2023年,该公司手机整体出货量约1.94亿部。

关键字: 传音 智能手机

最新消息,美国参议院以 79 票赞成、18 票反对的压倒性多数,通过了一项可能导致 TikTok 在美国被禁的法案,该法案要求字节跳动公司出售 TikTok,否则将面临禁令。TikTok 最多有 12 个月的时间从母公司...

关键字: 美国 TikTok 字节跳动

业内消息,近日数码博主@手机晶片达人在社交媒体发文表示,苹果公司正在研发自家的 AI 服务器芯片,采用台积电的 3nm 工艺,预估将于 2025 年下半年量产。台积电是苹果最重要的合作伙伴,目前苹果的大部分 3nm 产能...

关键字: 苹果 AI服务器芯片 台积电 3nm

业内消息,近日苹果公司公布了2023财年供应链名单。其中,中国大陆地区新进8家企业,有4家企业被剔除;中国台湾地区供应商新进2家企业,同样有4家企业被剔除。

关键字: 苹果 供应链
关闭