心跳机制在做PUSH和IM的时候一定会遇到。心跳说的是在客户端和服务端在互相建立ESTABLISH状态的时候,如何通过发送一个最简单的包来保持连接的存活,还有监控另外一遍服务的可用性等。
实际上,TCP协议层是有一个keepalive的机制的,这个是传输层进行设置的。但是往往,我们做具体应用的时候,会在应用层单独做一个心跳机制。这是为什么呢?大致有下面几个理由:
- 应用层心跳比传输层的心跳更好掌握
- 传输层心跳是保证连接可用,但应用层心跳却可以保证服务可用
总而言之,做网络服务基本上会自行实现一个心跳的。可以参考这篇
下面就是明确心跳协议的方向了,无外乎两种,从客户端向服务端定时发起心跳,或者从服务端向客户端定时发起心跳。
我们一般不会选择从服务端主动向客户端定时发送心跳的机制,因为这样对服务端的负载就比较高了。而且对于网络来说,瞬时网络压力有可能很大,所以一般都会使用由客户端主动发起心跳的机制。
心跳协议各种各样,如果是我们自己定制的网络包协议的话,最极致的就是使用一个空的tcp包作为心跳包。但是往往空网络包是一个非常“不稳定”的形态,有的会带一些类型或者版本号之类的。
如果觉得自定义网络协议包比较繁琐,或者可以尝试使用protobuffer来进行心跳包的设计。
总而言之,我们需要把心跳协议包设置越小越好。
心跳参数参考tcp的心跳参数,一般都会有三个参数:
- 最大空闲时间 //距离上次传送数据多少时间未收到判断为开始检测
- 最大心跳重试数 //发送几次心跳包对方未响应则close连接
- 重试间隔时间 // 重试每次间隔时间
一个好的服务在心跳检测的时候对这三个参数具体值的设置是非常有讲究的。但是这里说的讲究实际已经是经验领域了。
前面有说心跳有个功能是保活,比如一个IM,在不同的网络情况下,网络运营商(NAT)对“不活跃” 连接的判断都是不一样的。比如Line,会在国内、台湾、美国根据当地运营商使用不同的策略。
下面是Android微信智能心跳方案一篇总结的的不同心跳类型值。
文章列出了几个影响心跳连接寿命的因素
- NAT超时。 无线运营商判断“不活跃”连接的机制
- DHCP的租期。 客户端在DHCP租期到了之后是否主动续签等机制。
- 网络状态变化。 从3G,WIFI网络等切换的变化。
心跳机制说说容易,但是在具体做的时候,一定会碰上各种问题的,所以我说这个领域是“经验” 领域,即使你在技术层面了解这些机制,没有具体场景的体量的积累,具体实现的心跳机制只能说是玩具级别的...