• 网络编程-为什么需要应用层做心跳处理?


    背景

    许多小伙伴做网络编程时,会自然而然的去做应用层的心跳检测机制,如果问为什么要做心跳检测,大部分人会说保活,及时发现连接失效等等。这篇文章会结合TCP协议原理来分析,使用应用层做心跳检测的原因和必要性。

    没有应用层心跳检测时

    在没有应用层心跳检测时,我们如何发现对端应用程序崩溃/对端主机崩溃/主机不可达等等异常呢?

    假如网络正常
    我们考虑异常时在发送数据包:
    • 如果对端程序崩溃还未重启,会发送FIN,本端可以立即感知
    • 如果对端 程序崩溃/主机崩溃 后已经重启,会发送RST,本端可以立即感知
    • 对端主机崩溃一直未重启,我们发送的数据包将会TCP超时
    • 对端主机不可达,我们发送的数据包将会TCP超时

    TCP超时重传的默认机制是什么呢?

    首先明确,超时重传的原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。

    关于超时重传的时间间隔和重传次数,下面这篇博客比较详细的讲解了这个知识点:TCP/IP重传超时--RTO

    总结一下博客中的内容

    1. RTO有一个最小值,不同内核中是写死的,博客中提到的内核版本是200ms,就算RTT是0.5ms也不行的,会用200ms来发送第二次发送的数据包。
    2. TCP内核中可以修改两个参数
    /proc/sys/net/ipv4/tcp_retries1 (integer; default: 3)
    TCP尝试了3次(tcp_retries1默认3)重传后,还没有收到ACK的话,则后续每次重传都需要network layer先更新路由。
    
    /proc/sys/net/ipv4/tcp_retries2 (integer; default: 15)
    TCP默认最多做15次重传。根据RTO(retransmission timeout)不同,最后一次重传间隔大概是13到30分钟左右。如果15次重传都做完了,TCP/IP就会告诉应用层说:“搞不定了,包怎么都传不过去!”
    

    如果没有应用层心跳检测,我们发送的数据包,最差需要依靠TCP超时来判断对端出现问题,这个超时时间是很长的,在现代的业务中几乎无法满足业务的需求。

    我们考虑只接收对端数据包的过程:
    • 如果对端程序崩溃,会发送FIN,本端可以立即感知
    • 对端主机崩溃
      • 如果关闭了Tcp的KeepAlive保活机制,那么没有任何感知;
      • 如果开启了TCP keep_alive,会通过保活机制,发送几个检测包,要么超时,要么得到RST
    • 对端主机不可达,和上面的主机崩溃同理

    如果没有应用层心跳检测,我们在不发送,只接受的情况下,最差需要依靠Keep Alive机制的超时或RST来判断对端出现问题,超时时间为:2小时+75秒* 9次。这个时间在默认参数设置下也是很长的。另外,这三个参数也可以修改的:

    net.ipv4.tcp_keepalive_time 对应2小时
    net.ipv4.tcp_keepalive_intvl 对应75秒
    net.ipv4.tcp_keepalve_probes 对应9次
    
    假如网络异常

    假如有网络异常,但是对方主机和程序都正常

    发送数据包时:

    • 通过本端TCP超时,发现网络异常

    接收数据包时:

    • 通过Keep_Alive机制来探测

    有应用层心跳检测时

    通过上面的分析可以得知,对于网络应用,无论是依赖TCP超时还是Keep Alive,在最差的情况下的超时时间都是不可接受的。所以我们需要在应用层做一个类似的心跳检测机制,保证可以在任何情况下都可以快速的检测出异常情况。

    那么是否可以只发一次,在规定时间内没收到回复就判定连接异常呢?考虑下面的两种情况:

    • 网络波动,但是对端主机和服务都正常
    • 对端主机正忙于处理其他事务,响应慢了一些

    对这两种情况来说,如果检测一次,发现超时就判定连接失效基本属于误伤,可以通过多发送几次心跳检测包来规避上面的误伤情况。

    并且还需要考虑,在多次发送的心跳包,需要带序号,对端回复时,也要保证使用这个序号或者序号+1来匹配我们发出去的心跳包。如果编号对应不上,就不能算作此次检测成功了。

  • 相关阅读:
    【Python】脚本运行报错:IndentationError: unindent does not match any outer indentation level
    【托业】【新托业TOEIC新题型真题】学习笔记13-题库四-P7
    【Python】【面试必看】Python笔试题
    【JMeter】【微信好文收藏】Jmeter接口测试实战-有趣的cookie
    【托业】【新托业TOEIC新题型真题】学习笔记12-题库八-P7
    【Mock】mock-server 环境搭建
    【Linux】测试环境如何搭建?
    【Linux】常用指令、ps查看进程、kill杀进程、启动停止tomcat命令、查看日志、查看端口、find查找文件
    【SQL】SQL存储过程相关当前理解。(@temp=……)
    Vue.js+Koa2移动电商 笔记
  • 原文地址:https://www.cnblogs.com/ging/p/13467873.html
Copyright © 2020-2023  润新知