V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tuzhenyu
V2EX  ›  程序员

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

  •  
  •   tuzhenyu · 2017-11-21 15:46:07 +08:00 · 3390 次点击
    这是一个创建于 2554 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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