V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
tuzhenyu
V2EX  ›  程序员

请教大佬们一个关于 Netty 心跳机制的问题

  •  
  •   tuzhenyu · Nov 21, 2017 · 3825 views
    This topic created in 3091 days ago, the information mentioned may be changed or developed.

    Netty 创建的 Socket 连接,在一方断开连接时会触发对方的 channelInactive()方法,这样的话完全可以通过 channelInactive()方法判断对方是否存活,这样的话为什么还需要心跳机制来判断对方是否存活?

    比如,客户端因为某些原因宕机会造成 Socket 连接断开,连接断开会触发服务端的 channelInactive()方法,如果服务端的 channelInactive()方法未被触发就代表该连接的客户端依旧存活,这样服务端就能知道客户端的存活情况,也就不需要再用 IdleStateHandler 进行心跳检测了...

    我知道这样理解肯定有问题但是不知道问题在哪,请教大佬们...

    14 replies    2017-11-21 17:48:44 +08:00
    hcymk2
        1
    hcymk2  
       Nov 21, 2017
    心跳机制不光是来判断对方是否存活的吧。
    hsiafan
        2
    hsiafan  
       Nov 21, 2017
    断开连接需要两次挥手的,如果是 crash,路由器挂掉这种故障连发包的机会都没有,只能用心跳来检测。
    skydiver
        3
    skydiver  
       Nov 21, 2017
    TCP 连接双方都不发包的话无法知道连接断没断
    NUT
        4
    NUT  
       Nov 21, 2017
    idle 是空闲检测的意思,一般用来对于服务端来说, 如果客户端长时间不发心跳且在链接超时内(一般是写或者读超时),可以 closeChannel。这样资源消耗是可控的,毕竟不用服务端傻傻的等 。比如 对方 客户端的网关挂了( wifi 断网了),如果服务端没有写超时, 那么就得等到链接超时,一般这个时间比较长。

    超时的机制调优还是比较复杂。如果纯考客户端的上报请求, 那么流量消耗也是很恐怖的事情。
    tuzhenyu
        5
    tuzhenyu  
    OP
       Nov 21, 2017
    @xiaxiaocao 嗯嗯 谢谢 应该是这样的,如果心跳机制下客户端发送心跳包服务端只接收不回复,这种情况的心跳机制客户端是无法知道服务端的存活情况的吧?这种情况下服务端宕机客户端是不会关闭连接的吗?
    tuzhenyu
        6
    tuzhenyu  
    OP
       Nov 21, 2017
    @skydiver 我想应该是 TCP 连接断开时候的挥手数据包触发的 netty 的 channelInactive()方法
    tuzhenyu
        7
    tuzhenyu  
    OP
       Nov 21, 2017
    @NUT 请问一下,如果在客户端发送心跳包服务端只接收不回复的心跳机制下,服务端宕机后重启,客户端怎么实现重连呢?
    qiayue
        8
    qiayue  
    PRO
       Nov 21, 2017
    还有一个,无心跳的长连接,会被运营商踢掉
    NUT
        9
    NUT  
       Nov 21, 2017
    @tuzhenyu #7 这个问题有问题吧。链接方向只能 客户端链接服务端。 在 netty 中 客户端和服务端是相对的概念。可以定义 谁发起链接 谁就是 客户端。

    按照你的理解, 客户端重链接,首先 客户端需要有读的 idle (服务端的写过来的数据),其次有 链接异常的处理器。 如果有其中一个触发,就关闭链接,重新连接。 需要注意『链接状态』的状态机判断,并发也好考虑。 这玩意最好要用一个单独 manage 来做。 否则容易翻船。2333
    3dwelcome
        10
    3dwelcome  
       Nov 21, 2017
    楼主属于没接触过 TCP 掉线的,正常情况确实可以通过 channelInactive 来感知对方是否掉线。但问题是,TCP 非正常断开后(比如 wifi),服务器要过很久很久才会知道 socket 断开。

    所以用 Idle 来检测心跳,是很必要的。不然的话,黑客用大量 TCP 连接服务器端口,只 connect 上,不发数据,服务器对于这部分资源,是回收呢还是不回收呢?
    mrsatangel
        11
    mrsatangel  
       Nov 21, 2017 via iPhone
    如果客户端需要感知服务器的存活,要做双向心跳,由客户端发送心跳报文,服务器响应并返回心跳报文。超过某个阈值没有收到服务器的心跳响应,客户端启动断线重连。复杂一点的可能还需要服务端维护一个 session 用于客户端重连之后的状态恢复,存放在 redis 或者 hbase 里面。这玩意做起来 corner case 不少,心跳间隔、超时时间这些参数的优化也很玄学
    tuzhenyu
        12
    tuzhenyu  
    OP
       Nov 21, 2017
    @mrsatangel 哈哈 看来的确是需要双向心跳 谢谢
    tuzhenyu
        13
    tuzhenyu  
    OP
       Nov 21, 2017
    @3dwelcome 的确是这样的 谢谢
    tuzhenyu
        14
    tuzhenyu  
    OP
       Nov 21, 2017
    @NUT 恩恩 明白了 谢谢
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2978 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 07:08 · PVG 15:08 · LAX 00:08 · JFK 03:08
    ♥ Do have faith in what you're doing.