Netty 创建的 Socket 连接,在一方断开连接时会触发对方的 channelInactive()方法,这样的话完全可以通过 channelInactive()方法判断对方是否存活,这样的话为什么还需要心跳机制来判断对方是否存活?
比如,客户端因为某些原因宕机会造成 Socket 连接断开,连接断开会触发服务端的 channelInactive()方法,如果服务端的 channelInactive()方法未被触发就代表该连接的客户端依旧存活,这样服务端就能知道客户端的存活情况,也就不需要再用 IdleStateHandler 进行心跳检测了...
我知道这样理解肯定有问题但是不知道问题在哪,请教大佬们...
1
hcymk2 2017-11-21 15:54:43 +08:00
心跳机制不光是来判断对方是否存活的吧。
|
2
xiaxiaocao 2017-11-21 15:59:51 +08:00
断开连接需要两次挥手的,如果是 crash,路由器挂掉这种故障连发包的机会都没有,只能用心跳来检测。
|
3
skydiver 2017-11-21 16:10:49 +08:00
TCP 连接双方都不发包的话无法知道连接断没断
|
4
NUT 2017-11-21 16:18:28 +08:00
idle 是空闲检测的意思,一般用来对于服务端来说, 如果客户端长时间不发心跳且在链接超时内(一般是写或者读超时),可以 closeChannel。这样资源消耗是可控的,毕竟不用服务端傻傻的等 。比如 对方 客户端的网关挂了( wifi 断网了),如果服务端没有写超时, 那么就得等到链接超时,一般这个时间比较长。
超时的机制调优还是比较复杂。如果纯考客户端的上报请求, 那么流量消耗也是很恐怖的事情。 |
5
tuzhenyu OP @xiaxiaocao 嗯嗯 谢谢 应该是这样的,如果心跳机制下客户端发送心跳包服务端只接收不回复,这种情况的心跳机制客户端是无法知道服务端的存活情况的吧?这种情况下服务端宕机客户端是不会关闭连接的吗?
|
6
tuzhenyu OP @skydiver 我想应该是 TCP 连接断开时候的挥手数据包触发的 netty 的 channelInactive()方法
|
8
qiayue 2017-11-21 16:32:28 +08:00
还有一个,无心跳的长连接,会被运营商踢掉
|
9
NUT 2017-11-21 17:07:24 +08:00
@tuzhenyu #7 这个问题有问题吧。链接方向只能 客户端链接服务端。 在 netty 中 客户端和服务端是相对的概念。可以定义 谁发起链接 谁就是 客户端。
按照你的理解, 客户端重链接,首先 客户端需要有读的 idle (服务端的写过来的数据),其次有 链接异常的处理器。 如果有其中一个触发,就关闭链接,重新连接。 需要注意『链接状态』的状态机判断,并发也好考虑。 这玩意最好要用一个单独 manage 来做。 否则容易翻船。2333 |
10
3dwelcome 2017-11-21 17:28:13 +08:00
楼主属于没接触过 TCP 掉线的,正常情况确实可以通过 channelInactive 来感知对方是否掉线。但问题是,TCP 非正常断开后(比如 wifi),服务器要过很久很久才会知道 socket 断开。
所以用 Idle 来检测心跳,是很必要的。不然的话,黑客用大量 TCP 连接服务器端口,只 connect 上,不发数据,服务器对于这部分资源,是回收呢还是不回收呢? |
11
mrsatangel 2017-11-21 17:32:33 +08:00 via iPhone
如果客户端需要感知服务器的存活,要做双向心跳,由客户端发送心跳报文,服务器响应并返回心跳报文。超过某个阈值没有收到服务器的心跳响应,客户端启动断线重连。复杂一点的可能还需要服务端维护一个 session 用于客户端重连之后的状态恢复,存放在 redis 或者 hbase 里面。这玩意做起来 corner case 不少,心跳间隔、超时时间这些参数的优化也很玄学
|
12
tuzhenyu OP @mrsatangel 哈哈 看来的确是需要双向心跳 谢谢
|