美文网首页
心跳协议设计

心跳协议设计

作者: wayyyy | 来源:发表于2020-12-30 15:54 被阅读0次

    为什么需要应用层心跳?Tcp Keepalive 能不能代替心跳?

    • 保活
      一个客户端连接服务器以后,如果长期没有和服务器有数据来往,可能会被防火墙程序关闭连接,有时候我们并不想要被关闭连接。例如,对于一个即时通讯软件,如果服务器没有消息时,我们确实不会和服务器有任何数据交换,但是如果连接被关闭了,有新消息来时,我们再也没法收到了,这就违背了“即时通讯”的设计要求。

    • 检测死链
      服务器与某个客户端一般不是位于同一个网络,其之间可能经过数个路由器和交换机,如果其中某个必经路由器或者交换器出现了故障,并且一段时间内没有恢复,导致这之间的链路不再畅通,而此时服务器与客户端之间也没有数据进行交换,由于 TCP 连接是状态机,对于这种情况,无论是客户端或者服务器都无法感知与对方的连接是否正常,这类连接一般称之为“死链”。

    • 检测对端应用层状态
      心跳除了说明应用程序还活着以外(进程还在,网络通畅),更重要的是表明应用程序还能正常工作。而Tcp keepAlive由操作系统负责探测,即使进程死锁或阻塞,操作系统也会正常收发Tcp Keepalive。


    UDP需要设计心跳吗?

    UDP是无连接的,所以设计心跳没有意义。


    心跳协议设计

    其他注意事项
    • 要在工作线程发送,不要单独起一个心跳线程
      这是防止工作线程死锁活着阻塞时还在继续发心跳

    • 与业务消息用同一个心跳连接,不要单独使用 "心跳连接"
      心跳消息的作用之一就是验证网络畅通,如果它验证的不是收发业务数据的TCP连接畅通,那就没什么意义。

    心跳检测与调试

    在开发调试程序过程中,我们可能需要将程序通过断点中断下来,这个过程可能是几秒到几十秒不等。等程序恢复执行时,连接可能因为心跳检测逻辑已经被断开。

    调试过程中,我们更多的关注的是业务数据处理的逻辑是否正确,不想被一堆无意义的心跳包数据干扰实线。

    鉴于以上两点原因,我们一般在调试模式下关闭或者禁用心跳包检测机制。

    #ifndef _DEBUG
        EnableHeartCheck();
    #endif
    
    心跳检测与日志

    实际生产环境,一般会将程序收到的和发出去的数据包写入日志中,但是无业务信息的心跳包信息是个例外,一般会刻意不写入日志,这是因为心跳包数据一般比较多,如果写入日志会导致日志文件变得很大,且充斥大量无意义的心跳包日志,所以一般在写日志时会屏蔽心跳包信息写入。

    bool success = WebSocketSession::send(strResponse);
    if (success)
    {
        bool enablePingPongLog = Singleton<Config>::Instance().m_bPingPongLogEnabled;
        // 其他消息正常打印,心跳消息按需打印
        if (strResponse != "pong" || enablePingPongLog)
        {
            LOGI("...");
        }
    }
    

    参考资料
    1、http://101.37.25.166/blog/articles/%E9%AB%98%E6%80%A7%E8%83%BD%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%A1%86%E6%9E%B6%E8%AE%BE%E8%AE%A1/%E5%BF%83%E8%B7%B3%E5%8C%85%E6%9C%BA%E5%88%B6%E8%AE%BE%E8%AE%A1%E8%AF%A6%E8%A7%A3.html
    2、《Linux 多线程服务器端编程》

    相关文章

      网友评论

          本文标题:心跳协议设计

          本文链接:https://www.haomeiwen.com/subject/dfdjwktx.html