美文网首页
移动端心跳包

移动端心跳包

作者: topone37 | 来源:发表于2019-12-24 17:54 被阅读0次

    移动端心跳包

    TCP的心跳机制

    TCP协议,本身拥有一个KeepAlive机制,既然有了心跳机制,为什么还要在应用层面设计一个心跳包呢?

    1. TCPKeepAlive机制的局限, 应用层面的可用不等同于网络层面连接的存活状态

      TCP层面的keepalive存在更多意义上是为了检测两端连接是否正常,注重点是在于连接的本身,默认TCP的超时时间2小时太长,还会存在一些让keep-alive失效的场景

      • keepAlive只能检测连接存活,而不能检测连接可用,比如服务器因为负载过高导致无法响应请求但是连接仍然存在,此时keepalive无法判断连接是否可用

      • 如果TCP连接的另一端突然掉线,这个时候我们并不知道网络已经关闭。而此时,如果有发送数据失败,TCP会自动进行重传。重传包的优先级高于keepalive的包,那就意味着,我们的keepalive总是不能发送出去。 而此时,我们也并不知道该连接已经出错而中断。在较长时间的重传失败之后,我们才会知道。

    2. HTTPKeepAlive机制:复用tcp连接

      • HTTP/1.0之前,默认使用短连接,每进行一次HTTP操作,就简历一次连接,但任务结束就中断连接,

      • HTTP/1.1起,默认使用长连接,用以保持连接特性,复用同一个TCP连接,串行的来完成传递请求-响应数据,长连接的优势是节省了创建连接的耗时。

    应用层面的HeartBeat设计

    客户端开启一个定时任务,定时向已经建立连接的服务端发送请求(心跳包),服务端接收到后,就需要处理该特殊请求,返回响应,如果没有收到心跳响应多次,就认为连接不可用,进行重连

    • 心跳包的设计

      • 定时任务,频率设计(固定,)

      • 连接闲置才保活,避免流量浪费

      • 重试策略

      • 特定场景的触发,点亮屏幕,切换前台保证信息及时收到

      • 心跳间隔要小于NAT超时时间

    MQTT Android心跳包 AlarmPingSender

    • 定义了一个心跳包发送接口
      public void init();
      //开发发送心跳包
      public void start();
      //停止发送心跳包,可能是出错,获取连接关闭
      public void stop();
      //下一次心跳包的发送
      public void schedule(long delayInMilliseconds);
    
    • Android端 心跳包实现类
    private MqttService service = mqttService;
        ​
        public void start() {
         String action = "mqtt_heart_beat"
         //注册上对应广播接收器
         service.registerReceiver(alarmReceiver, new IntentFilter(action));
         //准备好 PendingIntent,每次都是定时发送一个广播
         pendingIntent = PendingIntent.getBroadcast(service, 0, 
         new Intent(action), PendingIntent.FLAG_UPDATE_CURRENT);
         //设置好下一次心跳包的发送
         schedule(interval_time);
        }
        //准备好下一次心跳
        public void schedule(long delayInMilliseconds) {
         //下一次心跳时间
         long nextAlarmInMilliseconds = System.currentTimeMillis()
         + delayInMilliseconds;
         //获取alarmManager
         AlarmManager alarmManager = (AlarmManager) service
         .getSystemService(Service.ALARM_SERVICE);
    
         //AlaramManager的兼容处理 定时任务
         if(Build.VERSION.SDK_INT >= 23){
         alarmManager.setExactAndAllowWhileIdle(
         AlarmManager.RTC_WAKEUP,nextAlarmInMilliseconds,pendingIntent);
         } else if (Build.VERSION.SDK_INT >= 19) {
         alarmManager.setExact(
         AlarmManager.RTC_WAKEUP,nextAlarmInMilliseconds,pendingIntent);
         } else {
         alarmManager.set(                            AlarmManager.RTC_WAKEUP,nextAlarmInMilliseconds,pendingIntent);
         }
         }
        ​
    
        //停止定时任务
        public void stop() {
         AlarmManager alarmManager = (AlarmManager)service.getSystemService(Service.ALARM_SERVICE);
         alarmManager.cancel(pendingIntent);
        }
        ​
        class AlarmReceiver extends BroadcastReceiver {
         private WakeLock wakelock;
    
         public void onReceive(Context context, Intent intent) {
         //AlaramManager持有的cpu wake_lock只能保证onReciver方法执行完成,但是我们需要在此处发送心跳包等,所以需要创建一个新的wake_lock
         PowerManager pm = (PowerManager) service
         .getSystemService(Service.POWER_SERVICE);
         wakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
         wakelock.acquire();
        ​
         //心跳包处理相关
         IMqttToken token = comms.checkForActivity();
         wakelock.release();
    
         }
         }
        // ClientComms#checkForActivity -> ClientStat#checkForActivity
        public MqttToken checkForActivity() {
         //将pingComond加入到发送数据流中
         pendingFlows.insertElementAt(pingCommand, 0);
         //获取下次心跳包时间
         nextPingTime = getKeepAlive();
         //准备下一次心跳包的发送
         pingSender.schedule(nextPingTime);
        }
    

    附录:

    • NAT超时

      • 因为 IP v4IP量有限,运营商分配给手机终端的 IP是运营商内网的IP,手机要连接Internet,就需要通过运营商的网关做一个网络地址转换(Network Address TranslationNAT)。简单的说运营商的网关需要维护一个外网IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟Internet的服务器通讯。
      • 大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰 NAT表中的对应项,造成链路中断。
      • 长连接心跳间隔必须要小于NAT超时时间(aging-time),如果超过aging-time不做心跳,TCP长连接链路就会中断,Server就无法发送Push给手机,只能等到客户端下次心跳失败后,重建连接才能取到消息。

    思考

    • 心跳机制保证了连接的可用性,保证推送信息的及时收取,但是为了及时收到信息,保活进程也是一个逃不开的手段,后续分析一下,进程的保活的手段

    参考链接

    相关文章

      网友评论

          本文标题:移动端心跳包

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